mirror of
https://github.com/osukey/osukey.git
synced 2025-06-08 21:07:59 +09:00
Merge branch 'master' into taiko-fixes
This commit is contained in:
commit
4087b638cf
@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
set { Curve.Distance = value; }
|
set { Curve.Distance = value; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<List<SampleInfo>> RepeatSamples { get; set; } = new List<List<SampleInfo>>();
|
public List<SampleInfoList> RepeatSamples { get; set; } = new List<SampleInfoList>();
|
||||||
public int RepeatCount { get; set; } = 1;
|
public int RepeatCount { get; set; } = 1;
|
||||||
|
|
||||||
private int stackHeight;
|
private int stackHeight;
|
||||||
@ -117,12 +117,12 @@ namespace osu.Game.Rulesets.Osu.Objects
|
|||||||
StackHeight = StackHeight,
|
StackHeight = StackHeight,
|
||||||
Scale = Scale,
|
Scale = Scale,
|
||||||
ComboColour = ComboColour,
|
ComboColour = ComboColour,
|
||||||
Samples = Samples.Select(s => new SampleInfo
|
Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
|
||||||
{
|
{
|
||||||
Bank = s.Bank,
|
Bank = s.Bank,
|
||||||
Name = @"slidertick",
|
Name = @"slidertick",
|
||||||
Volume = s.Volume
|
Volume = s.Volume
|
||||||
}).ToList()
|
}))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,9 +66,10 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
var distanceData = obj as IHasDistance;
|
var distanceData = obj as IHasDistance;
|
||||||
var repeatsData = obj as IHasRepeats;
|
var repeatsData = obj as IHasRepeats;
|
||||||
var endTimeData = obj as IHasEndTime;
|
var endTimeData = obj as IHasEndTime;
|
||||||
|
var curveData = obj as IHasCurve;
|
||||||
|
|
||||||
// Old osu! used hit sounding to determine various hit type information
|
// Old osu! used hit sounding to determine various hit type information
|
||||||
List<SampleInfo> samples = obj.Samples;
|
SampleInfoList samples = obj.Samples;
|
||||||
|
|
||||||
bool strong = samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
bool strong = samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
||||||
|
|
||||||
@ -102,16 +103,35 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
|||||||
|
|
||||||
if (tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength)
|
if (tickSpacing > 0 && osuDuration < 2 * speedAdjustedBeatLength)
|
||||||
{
|
{
|
||||||
|
List<SampleInfoList> allSamples = curveData != null ? curveData.RepeatSamples : new List<SampleInfoList>(new[] { samples });
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing)
|
for (double j = obj.StartTime; j <= obj.StartTime + taikoDuration + tickSpacing / 8; j += tickSpacing)
|
||||||
{
|
{
|
||||||
// Todo: This should generate different type of hits (including strongs)
|
SampleInfoList currentSamples = allSamples[i];
|
||||||
// depending on hitobject sound additions (not implemented fully yet)
|
bool isRim = currentSamples.Any(s => s.Name == SampleInfo.HIT_CLAP || s.Name == SampleInfo.HIT_WHISTLE);
|
||||||
yield return new CentreHit
|
strong = currentSamples.Any(s => s.Name == SampleInfo.HIT_FINISH);
|
||||||
|
|
||||||
|
if (isRim)
|
||||||
{
|
{
|
||||||
StartTime = j,
|
yield return new RimHit
|
||||||
Samples = obj.Samples,
|
{
|
||||||
IsStrong = strong,
|
StartTime = j,
|
||||||
};
|
Samples = currentSamples,
|
||||||
|
IsStrong = strong
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yield return new CentreHit
|
||||||
|
{
|
||||||
|
StartTime = j,
|
||||||
|
Samples = currentSamples,
|
||||||
|
IsStrong = strong,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
i = (i + 1) % allSamples.Count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -82,12 +82,12 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
|||||||
TickSpacing = tickSpacing,
|
TickSpacing = tickSpacing,
|
||||||
StartTime = t,
|
StartTime = t,
|
||||||
IsStrong = IsStrong,
|
IsStrong = IsStrong,
|
||||||
Samples = Samples.Select(s => new SampleInfo
|
Samples = new SampleInfoList(Samples.Select(s => new SampleInfo
|
||||||
{
|
{
|
||||||
Bank = s.Bank,
|
Bank = s.Bank,
|
||||||
Name = @"slidertick",
|
Name = @"slidertick",
|
||||||
Volume = s.Volume
|
Volume = s.Volume
|
||||||
}).ToList()
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
|
127
osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs
Normal file
127
osu.Game.Rulesets.Taiko/Objects/TaikoHitObjectDifficulty.cs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.Objects
|
||||||
|
{
|
||||||
|
internal class TaikoHitObjectDifficulty
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Factor by how much individual / overall strain decays per second.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// These values are results of tweaking a lot and taking into account general feedback.
|
||||||
|
/// </remarks>
|
||||||
|
internal const double DECAY_BASE = 0.30;
|
||||||
|
|
||||||
|
private const double type_change_bonus = 0.75;
|
||||||
|
private const double rhythm_change_bonus = 1.0;
|
||||||
|
private const double rhythm_change_base_threshold = 0.2;
|
||||||
|
private const double rhythm_change_base = 2.0;
|
||||||
|
|
||||||
|
internal TaikoHitObject BaseHitObject;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Measures note density in a way
|
||||||
|
/// </summary>
|
||||||
|
internal double Strain = 1;
|
||||||
|
|
||||||
|
private double timeElapsed;
|
||||||
|
private int sameTypeSince = 1;
|
||||||
|
|
||||||
|
private bool isRim => BaseHitObject is RimHit;
|
||||||
|
|
||||||
|
public TaikoHitObjectDifficulty(TaikoHitObject baseHitObject)
|
||||||
|
{
|
||||||
|
BaseHitObject = baseHitObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void CalculateStrains(TaikoHitObjectDifficulty previousHitObject, double timeRate)
|
||||||
|
{
|
||||||
|
// Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make.
|
||||||
|
// See Taiko feedback thread.
|
||||||
|
timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate;
|
||||||
|
double decay = Math.Pow(DECAY_BASE, timeElapsed / 1000);
|
||||||
|
|
||||||
|
double addition = 1;
|
||||||
|
|
||||||
|
// Only if we are no slider or spinner we get an extra addition
|
||||||
|
if (previousHitObject.BaseHitObject is Hit && BaseHitObject is Hit
|
||||||
|
&& BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime < 1000) // And we only want to check out hitobjects which aren't so far in the past
|
||||||
|
{
|
||||||
|
addition += typeChangeAddition(previousHitObject);
|
||||||
|
addition += rhythmChangeAddition(previousHitObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
double additionFactor = 1.0;
|
||||||
|
// Scale AdditionFactor linearly from 0.4 to 1 for TimeElapsed from 0 to 50
|
||||||
|
if (timeElapsed < 50.0)
|
||||||
|
additionFactor = 0.4 + 0.6 * timeElapsed / 50.0;
|
||||||
|
|
||||||
|
Strain = previousHitObject.Strain * decay + addition * additionFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeSwitch lastTypeSwitchEven = TypeSwitch.None;
|
||||||
|
private double typeChangeAddition(TaikoHitObjectDifficulty previousHitObject)
|
||||||
|
{
|
||||||
|
// If we don't have the same hit type, trigger a type change!
|
||||||
|
if (previousHitObject.isRim != isRim)
|
||||||
|
{
|
||||||
|
lastTypeSwitchEven = previousHitObject.sameTypeSince % 2 == 0 ? TypeSwitch.Even : TypeSwitch.Odd;
|
||||||
|
|
||||||
|
// We only want a bonus if the parity of the type switch changes!
|
||||||
|
switch (previousHitObject.lastTypeSwitchEven)
|
||||||
|
{
|
||||||
|
case TypeSwitch.Even:
|
||||||
|
if (lastTypeSwitchEven == TypeSwitch.Odd)
|
||||||
|
return type_change_bonus;
|
||||||
|
break;
|
||||||
|
case TypeSwitch.Odd:
|
||||||
|
if (lastTypeSwitchEven == TypeSwitch.Even)
|
||||||
|
return type_change_bonus;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No type change? Increment counter and keep track of last type switch
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastTypeSwitchEven = previousHitObject.lastTypeSwitchEven;
|
||||||
|
sameTypeSince = previousHitObject.sameTypeSince + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private double rhythmChangeAddition(TaikoHitObjectDifficulty previousHitObject)
|
||||||
|
{
|
||||||
|
// We don't want a division by zero if some random mapper decides to put 2 HitObjects at the same time.
|
||||||
|
if (timeElapsed == 0 || previousHitObject.timeElapsed == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
double timeElapsedRatio = Math.Max(previousHitObject.timeElapsed / timeElapsed, timeElapsed / previousHitObject.timeElapsed);
|
||||||
|
|
||||||
|
if (timeElapsedRatio >= 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
double difference = Math.Log(timeElapsedRatio, rhythm_change_base) % 1.0;
|
||||||
|
|
||||||
|
if (isWithinChangeThreshold(difference))
|
||||||
|
return rhythm_change_bonus;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool isWithinChangeThreshold(double value)
|
||||||
|
{
|
||||||
|
return value > rhythm_change_base_threshold && value < 1 - rhythm_change_base_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum TypeSwitch
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Even,
|
||||||
|
Odd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,18 +6,133 @@ using osu.Game.Rulesets.Beatmaps;
|
|||||||
using osu.Game.Rulesets.Taiko.Beatmaps;
|
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||||
using osu.Game.Rulesets.Taiko.Objects;
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko
|
namespace osu.Game.Rulesets.Taiko
|
||||||
{
|
{
|
||||||
public class TaikoDifficultyCalculator : DifficultyCalculator<TaikoHitObject>
|
internal class TaikoDifficultyCalculator : DifficultyCalculator<TaikoHitObject>
|
||||||
{
|
{
|
||||||
public TaikoDifficultyCalculator(Beatmap beatmap) : base(beatmap)
|
private const double star_scaling_factor = 0.04125;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// In milliseconds. For difficulty calculation we will only look at the highest strain value in each time interval of size STRAIN_STEP.
|
||||||
|
/// This is to eliminate higher influence of stream over aim by simply having more HitObjects with high strain.
|
||||||
|
/// The higher this value, the less strains there will be, indirectly giving long beatmaps an advantage.
|
||||||
|
/// </summary>
|
||||||
|
private const double strain_step = 400;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The weighting of each strain value decays to this number * it's previous value
|
||||||
|
/// </summary>
|
||||||
|
private const double decay_weight = 0.9;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HitObjects are stored as a member variable.
|
||||||
|
/// </summary>
|
||||||
|
private readonly List<TaikoHitObjectDifficulty> difficultyHitObjects = new List<TaikoHitObjectDifficulty>();
|
||||||
|
|
||||||
|
public TaikoDifficultyCalculator(Beatmap beatmap)
|
||||||
|
: base(beatmap)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
|
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty)
|
||||||
{
|
{
|
||||||
return 0;
|
// Fill our custom DifficultyHitObject class, that carries additional information
|
||||||
|
difficultyHitObjects.Clear();
|
||||||
|
|
||||||
|
foreach (var hitObject in Objects)
|
||||||
|
difficultyHitObjects.Add(new TaikoHitObjectDifficulty(hitObject));
|
||||||
|
|
||||||
|
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
|
||||||
|
difficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
|
||||||
|
|
||||||
|
if (!calculateStrainValues()) return 0;
|
||||||
|
|
||||||
|
double starRating = calculateDifficulty() * star_scaling_factor;
|
||||||
|
|
||||||
|
if (categoryDifficulty != null)
|
||||||
|
{
|
||||||
|
categoryDifficulty.Add("Strain", starRating.ToString("0.00", CultureInfo.InvariantCulture));
|
||||||
|
categoryDifficulty.Add("Hit window 300", (35 /*HitObjectManager.HitWindow300*/ / TimeRate).ToString("0.00", CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
|
||||||
|
return starRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool calculateStrainValues()
|
||||||
|
{
|
||||||
|
// Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment.
|
||||||
|
using (List<TaikoHitObjectDifficulty>.Enumerator hitObjectsEnumerator = difficultyHitObjects.GetEnumerator())
|
||||||
|
{
|
||||||
|
if (!hitObjectsEnumerator.MoveNext()) return false;
|
||||||
|
|
||||||
|
TaikoHitObjectDifficulty current = hitObjectsEnumerator.Current;
|
||||||
|
|
||||||
|
// First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject.
|
||||||
|
while (hitObjectsEnumerator.MoveNext())
|
||||||
|
{
|
||||||
|
var next = hitObjectsEnumerator.Current;
|
||||||
|
next?.CalculateStrains(current, TimeRate);
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double calculateDifficulty()
|
||||||
|
{
|
||||||
|
double actualStrainStep = strain_step * TimeRate;
|
||||||
|
|
||||||
|
// Find the highest strain value within each strain step
|
||||||
|
List<double> highestStrains = new List<double>();
|
||||||
|
double intervalEndTime = actualStrainStep;
|
||||||
|
double maximumStrain = 0; // We need to keep track of the maximum strain in the current interval
|
||||||
|
|
||||||
|
TaikoHitObjectDifficulty previousHitObject = null;
|
||||||
|
foreach (var hitObject in difficultyHitObjects)
|
||||||
|
{
|
||||||
|
// While we are beyond the current interval push the currently available maximum to our strain list
|
||||||
|
while (hitObject.BaseHitObject.StartTime > intervalEndTime)
|
||||||
|
{
|
||||||
|
highestStrains.Add(maximumStrain);
|
||||||
|
|
||||||
|
// The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay
|
||||||
|
// until the beginning of the next interval.
|
||||||
|
if (previousHitObject == null)
|
||||||
|
{
|
||||||
|
maximumStrain = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double decay = Math.Pow(TaikoHitObjectDifficulty.DECAY_BASE, (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000);
|
||||||
|
maximumStrain = previousHitObject.Strain * decay;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go to the next time interval
|
||||||
|
intervalEndTime += actualStrainStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtain maximum strain
|
||||||
|
maximumStrain = Math.Max(hitObject.Strain, maximumStrain);
|
||||||
|
|
||||||
|
previousHitObject = hitObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the weighted sum over the highest strains for each interval
|
||||||
|
double difficulty = 0;
|
||||||
|
double weight = 1;
|
||||||
|
highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain.
|
||||||
|
|
||||||
|
foreach (double strain in highestStrains)
|
||||||
|
{
|
||||||
|
difficulty += weight * strain;
|
||||||
|
weight *= decay_weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return difficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter() => new TaikoBeatmapConverter();
|
protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter() => new TaikoBeatmapConverter();
|
||||||
|
@ -81,6 +81,7 @@
|
|||||||
<Compile Include="Replays\TaikoFramedReplayInputHandler.cs" />
|
<Compile Include="Replays\TaikoFramedReplayInputHandler.cs" />
|
||||||
<Compile Include="Replays\TaikoAutoReplay.cs" />
|
<Compile Include="Replays\TaikoAutoReplay.cs" />
|
||||||
<Compile Include="Objects\TaikoHitObject.cs" />
|
<Compile Include="Objects\TaikoHitObject.cs" />
|
||||||
|
<Compile Include="Objects\TaikoHitObjectDifficulty.cs" />
|
||||||
<Compile Include="TaikoDifficultyCalculator.cs" />
|
<Compile Include="TaikoDifficultyCalculator.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Scoring\TaikoScoreProcessor.cs" />
|
<Compile Include="Scoring\TaikoScoreProcessor.cs" />
|
||||||
|
19
osu.Game/Audio/SampleInfoList.cs
Normal file
19
osu.Game/Audio/SampleInfoList.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// 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.Collections.Generic;
|
||||||
|
|
||||||
|
namespace osu.Game.Audio
|
||||||
|
{
|
||||||
|
public class SampleInfoList : List<SampleInfo>
|
||||||
|
{
|
||||||
|
public SampleInfoList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public SampleInfoList(IEnumerable<SampleInfo> elements)
|
||||||
|
{
|
||||||
|
AddRange(elements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -35,6 +35,10 @@ namespace osu.Game.Beatmaps
|
|||||||
protected DifficultyCalculator(Beatmap beatmap)
|
protected DifficultyCalculator(Beatmap beatmap)
|
||||||
{
|
{
|
||||||
Objects = CreateBeatmapConverter().Convert(beatmap).HitObjects;
|
Objects = CreateBeatmapConverter().Convert(beatmap).HitObjects;
|
||||||
|
|
||||||
|
foreach (var h in Objects)
|
||||||
|
h.ApplyDefaults(beatmap.TimingInfo, beatmap.BeatmapInfo.Difficulty);
|
||||||
|
|
||||||
PreprocessHitObjects();
|
PreprocessHitObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ using osu.Game.Audio;
|
|||||||
using osu.Game.Beatmaps.Timing;
|
using osu.Game.Beatmaps.Timing;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Objects
|
namespace osu.Game.Rulesets.Objects
|
||||||
{
|
{
|
||||||
@ -29,7 +28,7 @@ namespace osu.Game.Rulesets.Objects
|
|||||||
/// and can be treated as the default samples for the hit object.
|
/// and can be treated as the default samples for the hit object.
|
||||||
/// </para>
|
/// </para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<SampleInfo> Samples = new List<SampleInfo>();
|
public SampleInfoList Samples = new SampleInfoList();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Applies default values to this HitObject.
|
/// Applies default values to this HitObject.
|
||||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples)
|
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<SampleInfoList> repeatSamples)
|
||||||
{
|
{
|
||||||
return new ConvertSlider
|
return new ConvertSlider
|
||||||
{
|
{
|
||||||
|
@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate the final per-node samples
|
// Generate the final per-node samples
|
||||||
var nodeSamples = new List<List<SampleInfo>>(nodes);
|
var nodeSamples = new List<SampleInfoList>(nodes);
|
||||||
for (int i = 0; i <= repeatCount; i++)
|
for (int i = 0; i <= repeatCount; i++)
|
||||||
nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i]));
|
nodeSamples.Add(convertSoundType(nodeSoundTypes[i], nodeBankInfos[i]));
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
/// <param name="repeatCount">The slider repeat count.</param>
|
/// <param name="repeatCount">The slider repeat count.</param>
|
||||||
/// <param name="repeatSamples">The samples to be played when the repeat nodes are hit. This includes the head and tail of the slider.</param>
|
/// <param name="repeatSamples">The samples to be played when the repeat nodes are hit. This includes the head and tail of the slider.</param>
|
||||||
/// <returns>The hit object.</returns>
|
/// <returns>The hit object.</returns>
|
||||||
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples);
|
protected abstract HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<SampleInfoList> repeatSamples);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a legacy Spinner-type hit object.
|
/// Creates a legacy Spinner-type hit object.
|
||||||
@ -214,9 +214,9 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
/// <returns>The hit object.</returns>
|
/// <returns>The hit object.</returns>
|
||||||
protected abstract HitObject CreateSpinner(Vector2 position, double endTime);
|
protected abstract HitObject CreateSpinner(Vector2 position, double endTime);
|
||||||
|
|
||||||
private List<SampleInfo> convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
|
private SampleInfoList convertSoundType(LegacySoundType type, SampleBankInfo bankInfo)
|
||||||
{
|
{
|
||||||
var soundTypes = new List<SampleInfo>
|
var soundTypes = new SampleInfoList
|
||||||
{
|
{
|
||||||
new SampleInfo
|
new SampleInfo
|
||||||
{
|
{
|
||||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Objects.Legacy
|
|||||||
public CurveType CurveType { get; set; }
|
public CurveType CurveType { get; set; }
|
||||||
public double Distance { get; set; }
|
public double Distance { get; set; }
|
||||||
|
|
||||||
public List<List<SampleInfo>> RepeatSamples { get; set; }
|
public List<SampleInfoList> RepeatSamples { get; set; }
|
||||||
public int RepeatCount { get; set; } = 1;
|
public int RepeatCount { get; set; } = 1;
|
||||||
|
|
||||||
public double EndTime { get; set; }
|
public double EndTime { get; set; }
|
||||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Mania
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples)
|
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<SampleInfoList> repeatSamples)
|
||||||
{
|
{
|
||||||
return new ConvertSlider
|
return new ConvertSlider
|
||||||
{
|
{
|
||||||
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples)
|
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<SampleInfoList> repeatSamples)
|
||||||
{
|
{
|
||||||
return new ConvertSlider
|
return new ConvertSlider
|
||||||
{
|
{
|
||||||
|
@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Taiko
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<List<SampleInfo>> repeatSamples)
|
protected override HitObject CreateSlider(Vector2 position, bool newCombo, List<Vector2> controlPoints, double length, CurveType curveType, int repeatCount, List<SampleInfoList> repeatSamples)
|
||||||
{
|
{
|
||||||
return new ConvertSlider
|
return new ConvertSlider
|
||||||
{
|
{
|
||||||
|
@ -19,6 +19,6 @@ namespace osu.Game.Rulesets.Objects.Types
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The samples to be played when each repeat node is hit (0 -> first repeat node, 1 -> second repeat node, etc).
|
/// The samples to be played when each repeat node is hit (0 -> first repeat node, 1 -> second repeat node, etc).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<List<SampleInfo>> RepeatSamples { get; }
|
List<SampleInfoList> RepeatSamples { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Audio\SampleInfo.cs" />
|
<Compile Include="Audio\SampleInfo.cs" />
|
||||||
|
<Compile Include="Audio\SampleInfoList.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\BeatmapBackgroundSprite.cs" />
|
<Compile Include="Beatmaps\Drawables\BeatmapBackgroundSprite.cs" />
|
||||||
<Compile Include="Beatmaps\DifficultyCalculator.cs" />
|
<Compile Include="Beatmaps\DifficultyCalculator.cs" />
|
||||||
<Compile Include="Online\API\Requests\PostMessageRequest.cs" />
|
<Compile Include="Online\API\Requests\PostMessageRequest.cs" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user