mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 10:07:52 +08:00
Merge pull request #26578 from bdach/taiko-fail-no-hits
Fix taiko maps containing only drum rolls / swells not being passable without mods
This commit is contained in:
commit
981e959654
176
osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs
Normal file
176
osu.Game.Rulesets.Taiko.Tests/TaikoHealthProcessorTest.cs
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
// 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 NUnit.Framework;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Rulesets.Taiko.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Taiko.Judgements;
|
||||||
|
using osu.Game.Rulesets.Taiko.Objects;
|
||||||
|
using osu.Game.Rulesets.Taiko.Scoring;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Taiko.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TaikoHealthProcessorTest
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void TestHitsOnlyGreat()
|
||||||
|
{
|
||||||
|
var beatmap = new TaikoBeatmap
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new Hit(),
|
||||||
|
new Hit { StartTime = 1000 },
|
||||||
|
new Hit { StartTime = 2000 },
|
||||||
|
new Hit { StartTime = 3000 },
|
||||||
|
new Hit { StartTime = 4000 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var healthProcessor = new TaikoHealthProcessor();
|
||||||
|
healthProcessor.ApplyBeatmap(beatmap);
|
||||||
|
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new TaikoJudgement()) { Type = HitResult.Great });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], new TaikoJudgement()) { Type = HitResult.Great });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[2], new TaikoJudgement()) { Type = HitResult.Great });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[3], new TaikoJudgement()) { Type = HitResult.Great });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[4], new TaikoJudgement()) { Type = HitResult.Great });
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(healthProcessor.Health.Value, Is.EqualTo(1));
|
||||||
|
Assert.That(healthProcessor.HasFailed, Is.False);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHitsAboveThreshold()
|
||||||
|
{
|
||||||
|
var beatmap = new TaikoBeatmap
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new Hit(),
|
||||||
|
new Hit { StartTime = 1000 },
|
||||||
|
new Hit { StartTime = 2000 },
|
||||||
|
new Hit { StartTime = 3000 },
|
||||||
|
new Hit { StartTime = 4000 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var healthProcessor = new TaikoHealthProcessor();
|
||||||
|
healthProcessor.ApplyBeatmap(beatmap);
|
||||||
|
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new TaikoJudgement()) { Type = HitResult.Great });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], new TaikoJudgement()) { Type = HitResult.Ok });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[2], new TaikoJudgement()) { Type = HitResult.Ok });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[3], new TaikoJudgement()) { Type = HitResult.Ok });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[4], new TaikoJudgement()) { Type = HitResult.Miss });
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(healthProcessor.Health.Value, Is.GreaterThan(0.5));
|
||||||
|
Assert.That(healthProcessor.HasFailed, Is.False);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHitsBelowThreshold()
|
||||||
|
{
|
||||||
|
var beatmap = new TaikoBeatmap
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new Hit(),
|
||||||
|
new Hit { StartTime = 1000 },
|
||||||
|
new Hit { StartTime = 2000 },
|
||||||
|
new Hit { StartTime = 3000 },
|
||||||
|
new Hit { StartTime = 4000 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var healthProcessor = new TaikoHealthProcessor();
|
||||||
|
healthProcessor.ApplyBeatmap(beatmap);
|
||||||
|
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], new TaikoJudgement()) { Type = HitResult.Miss });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[1], new TaikoJudgement()) { Type = HitResult.Ok });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[2], new TaikoJudgement()) { Type = HitResult.Ok });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[3], new TaikoJudgement()) { Type = HitResult.Ok });
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[4], new TaikoJudgement()) { Type = HitResult.Miss });
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(healthProcessor.Health.Value, Is.LessThan(0.5));
|
||||||
|
Assert.That(healthProcessor.HasFailed, Is.True);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestDrumRollOnly()
|
||||||
|
{
|
||||||
|
var beatmap = new TaikoBeatmap
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new DrumRoll { Duration = 2000 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var ho in beatmap.HitObjects)
|
||||||
|
ho.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty);
|
||||||
|
|
||||||
|
var healthProcessor = new TaikoHealthProcessor();
|
||||||
|
healthProcessor.ApplyBeatmap(beatmap);
|
||||||
|
|
||||||
|
foreach (var nested in beatmap.HitObjects[0].NestedHitObjects)
|
||||||
|
{
|
||||||
|
var nestedJudgement = nested.CreateJudgement();
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(nested, nestedJudgement) { Type = nestedJudgement.MaxResult });
|
||||||
|
}
|
||||||
|
|
||||||
|
var judgement = beatmap.HitObjects[0].CreateJudgement();
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], judgement) { Type = judgement.MaxResult });
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(healthProcessor.Health.Value, Is.EqualTo(1));
|
||||||
|
Assert.That(healthProcessor.HasFailed, Is.False);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSwellOnly()
|
||||||
|
{
|
||||||
|
var beatmap = new TaikoBeatmap
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new DrumRoll { Duration = 2000 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var ho in beatmap.HitObjects)
|
||||||
|
ho.ApplyDefaults(beatmap.ControlPointInfo, beatmap.Difficulty);
|
||||||
|
|
||||||
|
var healthProcessor = new TaikoHealthProcessor();
|
||||||
|
healthProcessor.ApplyBeatmap(beatmap);
|
||||||
|
|
||||||
|
foreach (var nested in beatmap.HitObjects[0].NestedHitObjects)
|
||||||
|
{
|
||||||
|
var nestedJudgement = nested.CreateJudgement();
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(nested, nestedJudgement) { Type = nestedJudgement.MaxResult });
|
||||||
|
}
|
||||||
|
|
||||||
|
var judgement = beatmap.HitObjects[0].CreateJudgement();
|
||||||
|
healthProcessor.ApplyResult(new JudgementResult(beatmap.HitObjects[0], judgement) { Type = judgement.MaxResult });
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(healthProcessor.Health.Value, Is.EqualTo(1));
|
||||||
|
Assert.That(healthProcessor.HasFailed, Is.False);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,11 +31,39 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private double hpMissMultiplier;
|
private double hpMissMultiplier;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sum of all achievable health increases throughout the map.
|
||||||
|
/// Used to determine if there are any objects that give health.
|
||||||
|
/// If there are none, health will be forcibly pulled up to 1 to avoid cases of impassable maps.
|
||||||
|
/// </summary>
|
||||||
|
private double sumOfMaxHealthIncreases;
|
||||||
|
|
||||||
public TaikoHealthProcessor()
|
public TaikoHealthProcessor()
|
||||||
: base(0.5)
|
: base(0.5)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ApplyResultInternal(JudgementResult result)
|
||||||
|
{
|
||||||
|
base.ApplyResultInternal(result);
|
||||||
|
sumOfMaxHealthIncreases += result.Judgement.MaxHealthIncrease;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RevertResultInternal(JudgementResult result)
|
||||||
|
{
|
||||||
|
base.RevertResultInternal(result);
|
||||||
|
sumOfMaxHealthIncreases -= result.Judgement.MaxHealthIncrease;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Reset(bool storeResults)
|
||||||
|
{
|
||||||
|
base.Reset(storeResults);
|
||||||
|
|
||||||
|
if (storeResults && sumOfMaxHealthIncreases == 0)
|
||||||
|
Health.Value = 1;
|
||||||
|
sumOfMaxHealthIncreases = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public override void ApplyBeatmap(IBeatmap beatmap)
|
public override void ApplyBeatmap(IBeatmap beatmap)
|
||||||
{
|
{
|
||||||
base.ApplyBeatmap(beatmap);
|
base.ApplyBeatmap(beatmap);
|
||||||
|
Loading…
Reference in New Issue
Block a user