1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-23 08:27:23 +08:00

Merge pull request #31448 from bdach/automatic-new-combo-after-break

Force new combo on objects succeeding a break
This commit is contained in:
Bartłomiej Dach 2025-01-08 11:22:30 +01:00 committed by GitHub
commit e7070bd812
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 116 additions and 0 deletions

View File

@ -539,5 +539,85 @@ namespace osu.Game.Tests.Editing
Assert.That(beatmap.Breaks[0].EndTime, Is.EqualTo(5000 - OsuHitObject.PREEMPT_MAX));
});
}
[Test]
public void TestPuttingObjectBetweenBreakEndAndAnotherObjectForcesNewCombo()
{
var controlPoints = new ControlPointInfo();
controlPoints.Add(0, new TimingControlPoint { BeatLength = 500 });
var beatmap = new EditorBeatmap(new Beatmap
{
ControlPointInfo = controlPoints,
BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo },
Difficulty =
{
ApproachRate = 10,
},
HitObjects =
{
new HitCircle { StartTime = 1000, NewCombo = true },
new HitCircle { StartTime = 4500 },
new HitCircle { StartTime = 5000, NewCombo = true },
},
Breaks =
{
new BreakPeriod(2000, 4000),
}
});
foreach (var ho in beatmap.HitObjects)
ho.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty);
var beatmapProcessor = new EditorBeatmapProcessor(beatmap, new OsuRuleset());
beatmapProcessor.PreProcess();
beatmapProcessor.PostProcess();
Assert.Multiple(() =>
{
Assert.That(((HitCircle)beatmap.HitObjects[1]).NewCombo, Is.True);
Assert.That(((HitCircle)beatmap.HitObjects[2]).NewCombo, Is.True);
Assert.That(((HitCircle)beatmap.HitObjects[0]).ComboIndex, Is.EqualTo(1));
Assert.That(((HitCircle)beatmap.HitObjects[1]).ComboIndex, Is.EqualTo(2));
Assert.That(((HitCircle)beatmap.HitObjects[2]).ComboIndex, Is.EqualTo(3));
});
}
[Test]
public void TestAutomaticallyInsertedBreakForcesNewCombo()
{
var controlPoints = new ControlPointInfo();
controlPoints.Add(0, new TimingControlPoint { BeatLength = 500 });
var beatmap = new EditorBeatmap(new Beatmap
{
ControlPointInfo = controlPoints,
BeatmapInfo = { Ruleset = new OsuRuleset().RulesetInfo },
Difficulty =
{
ApproachRate = 10,
},
HitObjects =
{
new HitCircle { StartTime = 1000, NewCombo = true },
new HitCircle { StartTime = 5000 },
},
});
foreach (var ho in beatmap.HitObjects)
ho.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty);
var beatmapProcessor = new EditorBeatmapProcessor(beatmap, new OsuRuleset());
beatmapProcessor.PreProcess();
beatmapProcessor.PostProcess();
Assert.Multiple(() =>
{
Assert.That(beatmap.Breaks, Has.Count.EqualTo(1));
Assert.That(((HitCircle)beatmap.HitObjects[1]).NewCombo, Is.True);
Assert.That(((HitCircle)beatmap.HitObjects[0]).ComboIndex, Is.EqualTo(1));
Assert.That(((HitCircle)beatmap.HitObjects[1]).ComboIndex, Is.EqualTo(2));
});
}
}
}

View File

@ -41,6 +41,7 @@ namespace osu.Game.Screens.Edit
rulesetBeatmapProcessor?.PostProcess();
autoGenerateBreaks();
ensureNewComboAfterBreaks();
}
private void autoGenerateBreaks()
@ -100,5 +101,40 @@ namespace osu.Game.Screens.Edit
Beatmap.Breaks.Add(breakPeriod);
}
}
private void ensureNewComboAfterBreaks()
{
var breakEnds = Beatmap.Breaks.Select(b => b.EndTime).OrderBy(t => t).ToList();
if (breakEnds.Count == 0)
return;
int currentBreak = 0;
IHasComboInformation? lastObj = null;
bool comboInformationUpdateRequired = false;
foreach (var hitObject in Beatmap.HitObjects)
{
if (hitObject is not IHasComboInformation hasCombo)
continue;
if (currentBreak < breakEnds.Count && hitObject.StartTime >= breakEnds[currentBreak])
{
if (!hasCombo.NewCombo)
{
hasCombo.NewCombo = true;
comboInformationUpdateRequired = true;
}
currentBreak += 1;
}
if (comboInformationUpdateRequired)
hasCombo.UpdateComboInformation(lastObj);
lastObj = hasCombo;
}
}
}
}