Hopefully closes https://github.com/ppy/osu/issues/28284.
As far as I can tell this is a somewhat difficult one to reproduce
because it relies on a specific set of circumstances (at least the
reproduction case that I found does). The reset to frame 0 would
previously be called explicitly when `isHitting` changed:
182ca145c7/osu.Game.Rulesets.Mania/Skinning/Legacy/LegacyBodyPiece.cs (L144)
However, it can be the case that `bodyAnimation` is not loaded at the
point of this call. This is significant because
`SkinnableTextureAnimation` contains this logic:
182ca145c7/osu.Game/Skinning/LegacySkinExtensions.cs (L192-L211)
which cannot be moved any earlier (because any earlier the `Clock` may
no longer be correct), and also causes the animation to be seeked
forward while it is stopped.
I can't figure out a decent way to layer this otherwise (by scheduling
or whatever), so this commit is just applying the nuclear option of just
seeking back to frame 0 on every update frame in which the body piece is
not being hit.
Compare: https://github.com/ppy/osu/pull/26616
This came up elsewhere, namely in
https://github.com/ppy/osu/pull/28277#issuecomment-2133505958.
As it turns out, at least one beatmap among those whose scores had
unexpected changes in total score, namely
https://osu.ppy.sh/beatmapsets/971028#fruits/2062131, was using slider
velocity multipliers that were not a multiple of 0.01 (the specific
value used was 0.225x). This meant that due to the rounding applied to
`SliderVelocityMultiplierBindable` via `Precision`, the raw value was
being incorrectly rounded, resulting in incorrect conversion.
The "direct" change that revealed this is most likely
https://github.com/ppy/osu-framework/pull/6249, by the virtue of
shuffling the `BindableNumber` rounding code around and accidentally
changing midpoint rounding semantics in the process. But it was not
at fault here, as rounding was just as wrong before that change
as after in this specific context.
Test is an abridged / cropped version of
https://osu.ppy.sh/beatmapsets/971028#fruits/2062131 to demonstrate
the specific failure case (unfortunately can't use the whole beatmap
due to other conversion failures).
The very base class is the wrong place for it because
`FreeModSelectOverlay` inherits from it, and that one has different
assumptions and rules than "user" selection. In particular, in non-user
selection, more than one rate adjust mod may be active, which breaks the
mod speed hotkey's basic assumptions.