1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 18:47:27 +08:00

Prioritise hyperfruit over non-hyperfruit if simultaneous

In case of simultaneous hyperfruit and non-hyperfruit - which happen to
occur on some aspire maps - the desired behaviour is to hyperdash. This
did not previously occur, due to annoying details in how
`HitObjectContainer` is structured.

`HitObjectContainer`'s drawable comparer determines the order of
updating the objects. One could say that forcing the hyperfruit to be
updated last, after normal fruit, could help; unfortunately this is
complicated by the existence of juice streams and the fact that while a
juice stream can be terminated by a normal fruit that is coincidental
with a hyperfruit, the two are not comparable directly using the
comparer in any feasible way.

Therefore, apply a `Catcher`-level workaround that intends to handle
this locally; in short, if a hyperdash was toggled in a given frame, it
cannot be toggled off again in the same frame. This yields the desired
behaviour.
This commit is contained in:
Bartłomiej Dach 2023-12-04 09:30:18 +01:00
parent bb198e0c5a
commit fcb6f40666
No known key found for this signature in database

View File

@ -126,6 +126,7 @@ namespace osu.Game.Rulesets.Catch.UI
private Color4 hyperDashColour = DEFAULT_HYPER_DASH_COLOUR; private Color4 hyperDashColour = DEFAULT_HYPER_DASH_COLOUR;
private double? lastHyperDashStartTime;
private double hyperDashModifier = 1; private double hyperDashModifier = 1;
private int hyperDashDirection; private int hyperDashDirection;
private float hyperDashTargetPosition; private float hyperDashTargetPosition;
@ -233,16 +234,23 @@ namespace osu.Game.Rulesets.Catch.UI
// droplet doesn't affect the catcher state // droplet doesn't affect the catcher state
if (hitObject is TinyDroplet) return; if (hitObject is TinyDroplet) return;
if (result.IsHit && hitObject.HyperDashTarget is CatchHitObject target) // if a hyper fruit was already handled this frame, just go where it says to go.
// this special-cases some aspire maps that have doubled-up objects (one hyper, one not) at the same time instant.
// handling this "properly" elsewhere is impossible as there is no feasible way to ensure
// that the hyperfruit gets judged second (especially if it coincides with a last fruit in a juice stream).
if (lastHyperDashStartTime != Time.Current)
{ {
double timeDifference = target.StartTime - hitObject.StartTime; if (result.IsHit && hitObject.HyperDashTarget is CatchHitObject target)
double positionDifference = target.EffectiveX - X; {
double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0); double timeDifference = target.StartTime - hitObject.StartTime;
double positionDifference = target.EffectiveX - X;
double velocity = positionDifference / Math.Max(1.0, timeDifference - 1000.0 / 60.0);
SetHyperDashState(Math.Abs(velocity) / BASE_DASH_SPEED, target.EffectiveX); SetHyperDashState(Math.Abs(velocity) / BASE_DASH_SPEED, target.EffectiveX);
}
else
SetHyperDashState();
} }
else
SetHyperDashState();
if (result.IsHit) if (result.IsHit)
CurrentState = hitObject.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle; CurrentState = hitObject.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle;
@ -292,6 +300,8 @@ namespace osu.Game.Rulesets.Catch.UI
if (wasHyperDashing) if (wasHyperDashing)
runHyperDashStateTransition(false); runHyperDashStateTransition(false);
lastHyperDashStartTime = null;
} }
else else
{ {
@ -301,6 +311,8 @@ namespace osu.Game.Rulesets.Catch.UI
if (!wasHyperDashing) if (!wasHyperDashing)
runHyperDashStateTransition(true); runHyperDashStateTransition(true);
lastHyperDashStartTime = Time.Current;
} }
} }