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

Fix first object after break not starting a new combo

This commit is contained in:
Dan Balasescu 2023-11-16 20:21:11 +09:00
parent 87a76b9ee8
commit cb4568c4a1
No known key found for this signature in database
11 changed files with 65 additions and 34 deletions

View File

@ -1093,5 +1093,20 @@ namespace osu.Game.Tests.Beatmaps.Formats
Assert.That(hitObject.Samples.Select(s => s.Volume), Has.All.EqualTo(70));
}
}
[Test]
public void TestNewComboAfterBreak()
{
var decoder = new LegacyBeatmapDecoder { ApplyOffsets = false };
using (var resStream = TestResources.OpenResource("break-between-objects.osu"))
using (var stream = new LineBufferedReader(resStream))
{
var beatmap = decoder.Decode(stream);
Assert.That(((IHasCombo)beatmap.HitObjects[0]).NewCombo, Is.True);
Assert.That(((IHasCombo)beatmap.HitObjects[1]).NewCombo, Is.True);
Assert.That(((IHasCombo)beatmap.HitObjects[2]).NewCombo, Is.False);
}
}
}
}

View File

@ -94,9 +94,6 @@ namespace osu.Game.Tests.Gameplay
private class TestHitObjectWithCombo : ConvertHitObject, IHasComboInformation
{
public bool NewCombo { get; set; }
public int ComboOffset => 0;
public Bindable<int> IndexInCurrentComboBindable { get; } = new Bindable<int>();
public int IndexInCurrentCombo

View File

@ -0,0 +1,15 @@
osu file format v14
[General]
Mode: 0
[Events]
2,200,1200
[TimingPoints]
0,307.692307692308,4,2,1,60,1,0
[HitObjects]
142,99,0,1,0,0:0:0:0:
323,88,3000,1,0,0:0:0:0:
323,88,4000,1,0,0:0:0:0:

View File

@ -93,6 +93,8 @@ namespace osu.Game.Beatmaps.Formats
// The parsing order of hitobjects matters in mania difficulty calculation
this.beatmap.HitObjects = this.beatmap.HitObjects.OrderBy(h => h.StartTime).ToList();
postProcessBreaks(this.beatmap);
foreach (var hitObject in this.beatmap.HitObjects)
{
applyDefaults(hitObject);
@ -100,6 +102,27 @@ namespace osu.Game.Beatmaps.Formats
}
}
/// <summary>
/// Processes the beatmap such that a new combo is started the first hitobject following each break.
/// </summary>
private void postProcessBreaks(Beatmap beatmap)
{
int currentBreak = 0;
bool forceNewCombo = false;
foreach (var h in beatmap.HitObjects.OfType<ConvertHitObject>())
{
while (currentBreak < beatmap.Breaks.Count && beatmap.Breaks[currentBreak].EndTime < h.StartTime)
{
forceNewCombo = true;
currentBreak++;
}
h.NewCombo |= forceNewCombo;
forceNewCombo = false;
}
}
private void applyDefaults(HitObject hitObject)
{
DifficultyControlPoint difficultyControlPoint = (beatmap.ControlPointInfo as LegacyControlPointInfo)?.DifficultyPointAt(hitObject.StartTime) ?? DifficultyControlPoint.DEFAULT;

View File

@ -9,16 +9,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary>
/// Legacy osu!catch Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class ConvertHit : ConvertHitObject, IHasPosition, IHasCombo
internal sealed class ConvertHit : ConvertHitObject, IHasPosition
{
public float X => Position.X;
public float Y => Position.Y;
public Vector2 Position { get; set; }
public bool NewCombo { get; set; }
public int ComboOffset { get; set; }
}
}

View File

@ -9,16 +9,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary>
/// Legacy osu!catch Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasPosition, IHasCombo
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasPosition
{
public float X => Position.X;
public float Y => Position.Y;
public Vector2 Position { get; set; }
public bool NewCombo { get; set; }
public int ComboOffset { get; set; }
}
}

View File

@ -8,16 +8,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Catch
/// <summary>
/// Legacy osu!catch Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class ConvertSpinner : ConvertHitObject, IHasDuration, IHasXPosition, IHasCombo
internal sealed class ConvertSpinner : ConvertHitObject, IHasDuration, IHasXPosition
{
public double EndTime => StartTime + Duration;
public double Duration { get; set; }
public float X => 256; // Required for CatchBeatmapConverter
public bool NewCombo { get; set; }
public int ComboOffset { get; set; }
}
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Objects.Legacy
@ -9,8 +10,12 @@ namespace osu.Game.Rulesets.Objects.Legacy
/// <summary>
/// A hit object only used for conversion, not actual gameplay.
/// </summary>
internal abstract class ConvertHitObject : HitObject
internal abstract class ConvertHitObject : HitObject, IHasCombo
{
public bool NewCombo { get; set; }
public int ComboOffset { get; set; }
public override Judgement CreateJudgement() => new IgnoreJudgement();
protected override HitWindows CreateHitWindows() => HitWindows.Empty;

View File

@ -9,16 +9,12 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary>
/// Legacy osu! Hit-type, used for parsing Beatmaps.
/// </summary>
internal sealed class ConvertHit : ConvertHitObject, IHasPosition, IHasCombo
internal sealed class ConvertHit : ConvertHitObject, IHasPosition
{
public Vector2 Position { get; set; }
public float X => Position.X;
public float Y => Position.Y;
public bool NewCombo { get; set; }
public int ComboOffset { get; set; }
}
}

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary>
/// Legacy osu! Slider-type, used for parsing Beatmaps.
/// </summary>
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasPosition, IHasCombo, IHasGenerateTicks
internal sealed class ConvertSlider : Legacy.ConvertSlider, IHasPosition, IHasGenerateTicks
{
public Vector2 Position { get; set; }
@ -17,10 +17,6 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
public float Y => Position.Y;
public bool NewCombo { get; set; }
public int ComboOffset { get; set; }
public bool GenerateTicks { get; set; } = true;
}
}

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
/// <summary>
/// Legacy osu! Spinner-type, used for parsing Beatmaps.
/// </summary>
internal sealed class ConvertSpinner : ConvertHitObject, IHasDuration, IHasPosition, IHasCombo
internal sealed class ConvertSpinner : ConvertHitObject, IHasDuration, IHasPosition
{
public double Duration { get; set; }
@ -20,9 +20,5 @@ namespace osu.Game.Rulesets.Objects.Legacy.Osu
public float X => Position.X;
public float Y => Position.Y;
public bool NewCombo { get; set; }
public int ComboOffset { get; set; }
}
}