mirror of
https://github.com/ppy/osu.git
synced 2024-12-13 08:32:57 +08:00
Cause all earlier hitobjects to get missed
This commit is contained in:
parent
f285b43a74
commit
12a48d2774
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Replays;
|
||||
@ -24,6 +25,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
private const double time_first_circle = 1500;
|
||||
private const double time_second_circle = 1600;
|
||||
private const double early_miss_window = 1000; // time after -1000 to -500 is considered a miss
|
||||
private const double late_miss_window = 500; // time after +500 is considered a miss
|
||||
|
||||
private static readonly Vector2 position_first_circle = Vector2.Zero;
|
||||
private static readonly Vector2 position_second_circle = new Vector2(80);
|
||||
@ -40,6 +43,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
});
|
||||
|
||||
addJudgementAssert(HitResult.Miss, HitResult.Miss);
|
||||
addJudgementOffsetAssert(late_miss_window);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -54,6 +58,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
});
|
||||
|
||||
addJudgementAssert(HitResult.Miss, HitResult.Great);
|
||||
addJudgementOffsetAssert(0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -68,6 +73,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
});
|
||||
|
||||
addJudgementAssert(HitResult.Miss, HitResult.Great);
|
||||
addJudgementOffsetAssert(100);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -91,6 +97,11 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
AddAssert($"second circle judgement is {secondCircle}", () => judgementResults.Single(r => r.HitObject.StartTime == time_second_circle).Type == secondCircle);
|
||||
}
|
||||
|
||||
private void addJudgementOffsetAssert(double offset)
|
||||
{
|
||||
AddAssert($"first circle judged at {offset}", () => Precision.AlmostEquals(judgementResults.Single(r => r.HitObject.StartTime == time_first_circle).TimeOffset, offset, 100));
|
||||
}
|
||||
|
||||
private ScoreAccessibleReplayPlayer currentPlayer;
|
||||
private List<JudgementResult> judgementResults;
|
||||
private bool allJudgedFired;
|
||||
@ -157,7 +168,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
private static readonly DifficultyRange[] ranges =
|
||||
{
|
||||
new DifficultyRange(HitResult.Great, 500, 500, 500),
|
||||
new DifficultyRange(HitResult.Miss, 1000, 1000, 1000),
|
||||
new DifficultyRange(HitResult.Miss, early_miss_window, early_miss_window, early_miss_window),
|
||||
};
|
||||
|
||||
public override bool IsHitResultAllowed(HitResult result) => result == HitResult.Great || result == HitResult.Miss;
|
||||
|
@ -7,6 +7,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
@ -61,6 +62,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Causes this <see cref="DrawableOsuHitObject"/> to get missed, disregarding all conditions in implementations of <see cref="DrawableHitObject.CheckForResult"/>.
|
||||
/// </summary>
|
||||
public void MissForcefully() => ApplyResult(r => r.Type = HitResult.Miss);
|
||||
|
||||
protected override JudgementResult CreateResult(Judgement judgement) => new OsuJudgementResult(HitObject, judgement);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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 System;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osuTK;
|
||||
using osu.Framework.Graphics;
|
||||
@ -104,6 +105,8 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
|
||||
private void onNewResult(DrawableHitObject judgedObject, JudgementResult result)
|
||||
{
|
||||
missAllEarlier(result);
|
||||
|
||||
if (!judgedObject.DisplayResult || !DisplayJudgements.Value)
|
||||
return;
|
||||
|
||||
@ -117,6 +120,55 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
judgementLayer.Add(explosion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Misses all <see cref="OsuHitObject"/>s occurring earlier than the start time of a judged <see cref="OsuHitObject"/>.
|
||||
/// </summary>
|
||||
/// <param name="result">The <see cref="JudgementResult"/> of the judged <see cref="OsuHitObject"/>.</param>
|
||||
private void missAllEarlier(JudgementResult result)
|
||||
{
|
||||
// Hitobjects that count as bonus should not cause other hitobjects to get missed.
|
||||
// E.g. For the sequence slider-head -> circle -> slider-tick, hitting the tick before the circle should not cause the circle to be missed.
|
||||
// E.g. For the sequence spinner -> circle -> spinner-bonus, hitting the bonus before the circle should not cause the circle to be missed.
|
||||
if (result.Judgement.IsBonus)
|
||||
return;
|
||||
|
||||
// The minimum start time required for hitobjects so that they aren't missed.
|
||||
double minimumTime = result.HitObject.StartTime;
|
||||
|
||||
foreach (var obj in HitObjectContainer.AliveObjects)
|
||||
{
|
||||
if (obj.HitObject.StartTime >= minimumTime)
|
||||
break;
|
||||
|
||||
attemptMiss(obj);
|
||||
|
||||
foreach (var n in obj.NestedHitObjects)
|
||||
{
|
||||
if (n.HitObject.StartTime >= minimumTime)
|
||||
break;
|
||||
|
||||
attemptMiss(n);
|
||||
}
|
||||
}
|
||||
|
||||
static void attemptMiss(DrawableHitObject obj)
|
||||
{
|
||||
if (!(obj is DrawableOsuHitObject osuObject))
|
||||
throw new InvalidOperationException($"{obj.GetType()} is not a {nameof(DrawableOsuHitObject)}.");
|
||||
|
||||
// Hitobjects that have already been judged cannot be missed.
|
||||
if (osuObject.Judged)
|
||||
return;
|
||||
|
||||
// Hitobjects that count as bonus should not be missed.
|
||||
// For the sequence slider-head -> slider-tick -> circle, hitting the circle before the tick should not cause the tick to be missed.
|
||||
if (osuObject.Result.Judgement.IsBonus)
|
||||
return;
|
||||
|
||||
osuObject.MissForcefully();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => HitObjectContainer.ReceivePositionalInputAt(screenSpacePos);
|
||||
|
||||
private class ApproachCircleProxyContainer : LifetimeManagementContainer
|
||||
|
Loading…
Reference in New Issue
Block a user