diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs
index 744e207b57..e53fe01157 100644
--- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs
+++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform/Objects/Drawables/DrawableEmptyFreeformHitObject.cs
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.EmptyFreeform.Objects.Drawables
{
if (timeOffset >= 0)
// todo: implement judgement logic
- ApplyResult(r => r.Type = HitResult.Perfect);
+ ApplyResult(HitResult.Perfect);
}
protected override void UpdateHitStateTransforms(ArmedState state)
diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs
index c5ada4288d..b1be25727f 100644
--- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs
+++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs
@@ -9,7 +9,6 @@ using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Audio;
using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.Scoring;
using osuTK;
using osuTK.Graphics;
@@ -49,7 +48,12 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
if (timeOffset >= 0)
- ApplyResult(r => r.Type = IsHovered ? HitResult.Perfect : HitResult.Miss);
+ {
+ if (IsHovered)
+ ApplyMaxResult();
+ else
+ ApplyMinResult();
+ }
}
protected override double InitialLifetimeOffset => time_preempt;
diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs
index a3c3b89105..adcbd36485 100644
--- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs
+++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling/Objects/Drawables/DrawableEmptyScrollingHitObject.cs
@@ -3,7 +3,6 @@
using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
-using osu.Game.Rulesets.Scoring;
using osuTK;
using osuTK.Graphics;
@@ -24,7 +23,7 @@ namespace osu.Game.Rulesets.EmptyScrolling.Objects.Drawables
{
if (timeOffset >= 0)
// todo: implement judgement logic
- ApplyResult(r => r.Type = HitResult.Perfect);
+ ApplyMaxResult();
}
protected override void UpdateHitStateTransforms(ArmedState state)
diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs
index d198fa81cb..3ad636a601 100644
--- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs
+++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon/Objects/Drawables/DrawablePippidonHitObject.cs
@@ -10,7 +10,6 @@ using osu.Framework.Graphics.Textures;
using osu.Game.Audio;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Pippidon.UI;
-using osu.Game.Rulesets.Scoring;
using osuTK;
using osuTK.Graphics;
@@ -49,7 +48,12 @@ namespace osu.Game.Rulesets.Pippidon.Objects.Drawables
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
if (timeOffset >= 0)
- ApplyResult(r => r.Type = currentLane.Value == HitObject.Lane ? HitResult.Perfect : HitResult.Miss);
+ {
+ if (currentLane.Value == HitObject.Lane)
+ ApplyMaxResult();
+ else
+ ApplyMinResult();
+ }
}
protected override void UpdateHitStateTransforms(ArmedState state)
diff --git a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs
index 7f8c17861d..64705f9909 100644
--- a/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs
+++ b/osu.Game.Rulesets.Catch/Objects/Drawables/DrawableCatchHitObject.cs
@@ -63,7 +63,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawables
if (CheckPosition == null) return;
if (timeOffset >= 0 && Result != null)
- ApplyResult(r => r.Type = CheckPosition.Invoke(HitObject) ? r.Judgement.MaxResult : r.Judgement.MinResult);
+ {
+ if (CheckPosition.Invoke(HitObject))
+ ApplyMaxResult();
+ else
+ ApplyMinResult();
+ }
}
protected override void UpdateHitStateTransforms(ArmedState state)
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
index 3490d50871..2b55e81788 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNote.cs
@@ -265,7 +265,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (Tail.AllJudged)
{
if (Tail.IsHit)
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
else
MissForcefully();
}
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs
index 1b2efbafdf..6259033235 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableHoldNoteBody.cs
@@ -25,7 +25,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
{
if (AllJudged) return;
- ApplyResult(r => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult);
+ if (hit)
+ ApplyMaxResult();
+ else
+ ApplyMinResult();
}
}
}
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs
index 8498fd36de..e98622b8bf 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableManiaHitObject.cs
@@ -87,7 +87,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
///
/// Causes this to get missed, disregarding all conditions in implementations of .
///
- public virtual void MissForcefully() => ApplyResult(r => r.Type = r.Judgement.MinResult);
+ public virtual void MissForcefully() => ApplyMinResult();
}
public abstract partial class DrawableManiaHitObject : DrawableManiaHitObject
diff --git a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs
index 680009bc4c..f6b92ab405 100644
--- a/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs
+++ b/osu.Game.Rulesets.Mania/Objects/Drawables/DrawableNote.cs
@@ -89,18 +89,18 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (!userTriggered)
{
if (!HitObject.HitWindows.CanBeHit(timeOffset))
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
return;
}
var result = HitObject.HitWindows.ResultFor(timeOffset);
+
if (result == HitResult.None)
return;
result = GetCappedResult(result);
-
- ApplyResult(r => r.Type = result);
+ ApplyResult(result);
}
///
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs
index 30b0451a3b..abe950f9bb 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircle.cs
@@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Tests
if (auto && !userTriggered && timeOffset > hitOffset && CheckHittable?.Invoke(this, Time.Current, HitResult.Great) == ClickAction.Hit)
{
// force success
- ApplyResult(r => r.Type = HitResult.Great);
+ ApplyResult(HitResult.Great);
}
else
base.CheckForResult(userTriggered, timeOffset);
diff --git a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs
index 7824f26251..838b426cb4 100644
--- a/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs
+++ b/osu.Game.Rulesets.Osu.Tests/TestSceneHitCircleLateFade.cs
@@ -208,7 +208,7 @@ namespace osu.Game.Rulesets.Osu.Tests
if (shouldHit && !userTriggered && timeOffset >= 0)
{
// force success
- ApplyResult(r => r.Type = HitResult.Great);
+ ApplyResult(HitResult.Great);
}
else
base.CheckForResult(userTriggered, timeOffset);
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
index 0d665cad0c..b1c9bef6c4 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs
@@ -155,7 +155,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (!userTriggered)
{
if (!HitObject.HitWindows.CanBeHit(timeOffset))
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
return;
}
@@ -169,19 +169,22 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (result == HitResult.None || clickAction != ClickAction.Hit)
return;
- ApplyResult(r =>
+ Vector2? hitPosition = null;
+
+ // Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss.
+ if (result.IsHit())
+ {
+ var localMousePosition = ToLocalSpace(inputManager.CurrentState.Mouse.Position);
+ hitPosition = HitObject.StackedPosition + (localMousePosition - DrawSize / 2);
+ }
+
+ ApplyResult<(HitResult result, Vector2? position)>((r, state) =>
{
var circleResult = (OsuHitCircleJudgementResult)r;
- // Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss.
- if (result.IsHit())
- {
- var localMousePosition = ToLocalSpace(inputManager.CurrentState.Mouse.Position);
- circleResult.CursorPositionAtHit = HitObject.StackedPosition + (localMousePosition - DrawSize / 2);
- }
-
- circleResult.Type = result;
- });
+ circleResult.Type = state.result;
+ circleResult.CursorPositionAtHit = state.position;
+ }, (result, hitPosition));
}
///
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
index 5b379a0d90..5271c03e08 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs
@@ -100,12 +100,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
///
/// Causes this to get hit, disregarding all conditions in implementations of .
///
- public void HitForcefully() => ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ public void HitForcefully() => ApplyMaxResult();
///
/// Causes this to get missed, disregarding all conditions in implementations of .
///
- public void MissForcefully() => ApplyResult(r => r.Type = r.Judgement.MinResult);
+ public void MissForcefully() => ApplyMinResult();
private RectangleF parentScreenSpaceRectangle => ((DrawableOsuHitObject)ParentHitObject)?.parentScreenSpaceRectangle ?? Parent!.ScreenSpaceDrawQuad.AABBFloat;
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
index 080d07be49..6d492e7b08 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSlider.cs
@@ -292,10 +292,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (HitObject.ClassicSliderBehaviour)
{
// Classic behaviour means a slider is judged proportionally to the number of nested hitobjects hit. This is the classic osu!stable scoring.
- ApplyResult(r =>
+ ApplyResult(static (r, hitObject) =>
{
- int totalTicks = NestedHitObjects.Count;
- int hitTicks = NestedHitObjects.Count(h => h.IsHit);
+ int totalTicks = hitObject.NestedHitObjects.Count;
+ int hitTicks = hitObject.NestedHitObjects.Count(h => h.IsHit);
if (hitTicks == totalTicks)
r.Type = HitResult.Great;
@@ -312,7 +312,10 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
// If only the nested hitobjects are judged, then the slider's own judgement is ignored for scoring purposes.
// But the slider needs to still be judged with a reasonable hit/miss result for visual purposes (hit/miss transforms, etc).
- ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
+ ApplyResult(static (r, hitObject) =>
+ {
+ r.Type = hitObject.NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult;
+ });
}
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
index 9a98286738..11120e49b5 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs
@@ -258,15 +258,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
foreach (var tick in ticks.Where(t => !t.Result.HasResult))
tick.TriggerResult(false);
- ApplyResult(r =>
+ ApplyResult(static (r, hitObject) =>
{
- if (Progress >= 1)
+ var spinner = (DrawableSpinner)hitObject;
+ if (spinner.Progress >= 1)
r.Type = HitResult.Great;
- else if (Progress > .9)
+ else if (spinner.Progress > .9)
r.Type = HitResult.Ok;
- else if (Progress > .75)
+ else if (spinner.Progress > .75)
r.Type = HitResult.Meh;
- else if (Time.Current >= HitObject.EndTime)
+ else if (spinner.Time.Current >= spinner.HitObject.EndTime)
r.Type = r.Judgement.MinResult;
});
}
diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
index 5b55533edd..0a77faf924 100644
--- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
+++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinnerTick.cs
@@ -35,6 +35,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
/// Apply a judgement result.
///
/// Whether this tick was reached.
- internal void TriggerResult(bool hit) => ApplyResult(r => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult);
+ internal void TriggerResult(bool hit)
+ {
+ if (hit)
+ ApplyMaxResult();
+ else
+ ApplyMinResult();
+ }
}
}
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs
index 2bf0c04adf..1af4719b02 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRoll.cs
@@ -143,7 +143,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (timeOffset < 0)
return;
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
}
protected override void UpdateHitStateTransforms(ArmedState state)
@@ -192,7 +192,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (!ParentHitObject.Judged)
return;
- ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult);
+ ApplyResult(static (r, hitObject) =>
+ {
+ var drumRoll = (StrongNestedHit)hitObject;
+ r.Type = drumRoll.ParentHitObject!.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult;
+ });
}
public override bool OnPressed(KeyBindingPressEvent e) => false;
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
index c900165d34..0333fd71a9 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableDrumRollTick.cs
@@ -49,14 +49,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (!userTriggered)
{
if (timeOffset > HitObject.HitWindow)
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
return;
}
if (Math.Abs(timeOffset) > HitObject.HitWindow)
return;
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
}
public override void OnKilled()
@@ -64,7 +64,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
base.OnKilled();
if (Time.Current > HitObject.GetEndTime() && !Judged)
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
}
protected override void UpdateHitStateTransforms(ArmedState state)
@@ -105,7 +105,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (!ParentHitObject.Judged)
return;
- ApplyResult(r => r.Type = ParentHitObject.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult);
+ ApplyResult(static (r, hitObject) =>
+ {
+ var nestedHit = (StrongNestedHit)hitObject;
+ r.Type = nestedHit.ParentHitObject!.IsHit ? r.Judgement.MaxResult : r.Judgement.MinResult;
+ });
}
public override bool OnPressed(KeyBindingPressEvent e) => false;
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs
index a039ce3407..aad9214c5e 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableFlyingHit.cs
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
protected override void LoadComplete()
{
base.LoadComplete();
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
}
protected override void LoadSamples()
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
index 1ef426854e..4fb69056da 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableHit.cs
@@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (!userTriggered)
{
if (!HitObject.HitWindows.CanBeHit(timeOffset))
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
return;
}
@@ -108,9 +108,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
return;
if (!validActionPressed)
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
else
- ApplyResult(r => r.Type = result);
+ ApplyResult(result);
}
public override bool OnPressed(KeyBindingPressEvent e)
@@ -209,19 +209,19 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (!ParentHitObject.Result.IsHit)
{
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
return;
}
if (!userTriggered)
{
if (timeOffset - ParentHitObject.Result.TimeOffset > SECOND_HIT_WINDOW)
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
return;
}
if (Math.Abs(timeOffset - ParentHitObject.Result.TimeOffset) <= SECOND_HIT_WINDOW)
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
}
public override bool OnPressed(KeyBindingPressEvent e)
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs
index 724d59edcd..11759927a9 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableStrongNestedHit.cs
@@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
// it can happen that the hit window of the nested strong hit extends past the lifetime of the parent object.
// this is a safety to prevent such cases from causing the nested hit to never be judged and as such prevent gameplay from completing.
if (!Judged && Time.Current > ParentHitObject?.HitObject.GetEndTime())
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
}
}
}
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs
index e4a083f218..e1fc28fe16 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwell.cs
@@ -206,7 +206,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint);
if (numHits == HitObject.RequiredHits)
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
}
else
{
@@ -227,7 +227,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
tick.TriggerResult(false);
}
- ApplyResult(r => r.Type = numHits == HitObject.RequiredHits ? r.Judgement.MaxResult : r.Judgement.MinResult);
+ if (numHits == HitObject.RequiredHits)
+ ApplyMaxResult();
+ else
+ ApplyMinResult();
}
}
diff --git a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs
index 3a5c006962..04dd01e066 100644
--- a/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs
+++ b/osu.Game.Rulesets.Taiko/Objects/Drawables/DrawableSwellTick.cs
@@ -30,7 +30,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
public void TriggerResult(bool hit)
{
HitObject.StartTime = Time.Current;
- ApplyResult(r => r.Type = hit ? r.Judgement.MaxResult : r.Judgement.MinResult);
+
+ if (hit)
+ ApplyMaxResult();
+ else
+ ApplyMinResult();
}
protected override void CheckForResult(bool userTriggered, double timeOffset)
diff --git a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs
index 10dbede2e0..73177e36e1 100644
--- a/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs
+++ b/osu.Game.Tests/Gameplay/TestSceneDrawableHitObject.cs
@@ -216,7 +216,7 @@ namespace osu.Game.Tests.Gameplay
LifetimeStart = LIFETIME_ON_APPLY;
}
- public void MissForcefully() => ApplyResult(r => r.Type = HitResult.Miss);
+ public void MissForcefully() => ApplyResult(HitResult.Miss);
protected override void UpdateHitStateTransforms(ArmedState state)
{
diff --git a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs
index fea7456472..b567e8de8d 100644
--- a/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs
+++ b/osu.Game.Tests/Visual/Gameplay/TestScenePoolingRuleset.cs
@@ -431,7 +431,7 @@ namespace osu.Game.Tests.Visual.Gameplay
protected override void CheckForResult(bool userTriggered, double timeOffset)
{
if (timeOffset > HitObject.Duration)
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
}
protected override void UpdateHitStateTransforms(ArmedState state)
@@ -468,7 +468,7 @@ namespace osu.Game.Tests.Visual.Gameplay
public override void OnKilled()
{
base.OnKilled();
- ApplyResult(r => r.Type = r.Judgement.MinResult);
+ ApplyMinResult();
}
}
@@ -547,7 +547,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
base.CheckForResult(userTriggered, timeOffset);
if (timeOffset >= 0)
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
}
}
@@ -596,7 +596,7 @@ namespace osu.Game.Tests.Visual.Gameplay
{
base.CheckForResult(userTriggered, timeOffset);
if (timeOffset >= 0)
- ApplyResult(r => r.Type = r.Judgement.MaxResult);
+ ApplyMaxResult();
}
}
diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs
index b781a13929..4b98df50d7 100644
--- a/osu.Game/Rulesets/Judgements/JudgementResult.cs
+++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs
@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Judgements
///
/// The time at which this occurred.
- /// Populated when this is applied via .
+ /// Populated when this is applied via .
///
///
/// This is used instead of to check whether this should be reverted.
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index 161537200a..c9192ae3eb 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -683,17 +683,31 @@ namespace osu.Game.Rulesets.Objects.Drawables
UpdateResult(false);
}
+ protected void ApplyMaxResult() => ApplyResult((r, _) => r.Type = r.Judgement.MaxResult);
+ protected void ApplyMinResult() => ApplyResult((r, _) => r.Type = r.Judgement.MinResult);
+
+ protected void ApplyResult(HitResult type) => ApplyResult(static (result, state) => result.Type = state, type);
+
+ [Obsolete("Use overload with state, preferrably with static delegates to avoid allocation overhead.")] // Can be removed 2024-07-26
+ protected void ApplyResult(Action application) => ApplyResult((r, _) => application(r), this);
+
+ protected void ApplyResult(Action application) => ApplyResult(application, this);
+
///
/// Applies the of this , notifying responders such as
/// the of the .
///
- /// The callback that applies changes to the .
- protected void ApplyResult(Action application)
+ /// The callback that applies changes to the . Using a `static` delegate is recommended to avoid allocation overhead.
+ ///
+ /// Use this parameter to pass any data that requires
+ /// to apply a result, so that it can remain a `static` delegate and thus not allocate.
+ ///
+ protected void ApplyResult(Action application, T state)
{
if (Result.HasResult)
throw new InvalidOperationException("Cannot apply result on a hitobject that already has a result.");
- application?.Invoke(Result);
+ application?.Invoke(Result, state);
if (!Result.HasResult)
throw new InvalidOperationException($"{GetType().ReadableName()} applied a {nameof(JudgementResult)} but did not update {nameof(JudgementResult.Type)}.");
@@ -738,7 +752,7 @@ namespace osu.Game.Rulesets.Objects.Drawables
/// Checks if a scoring result has occurred for this .
///
///
- /// If a scoring result has occurred, this method must invoke to update the result and notify responders.
+ /// If a scoring result has occurred, this method must invoke to update the result and notify responders.
///
/// Whether the user triggered this check.
/// The offset from the end time of the at which this check occurred.