mirror of
https://github.com/ppy/osu.git
synced 2026-06-05 17:54:14 +08:00
Another batch of small rhythm evaluation fixes (#37609)
## [Reduce rhythm effective ratio for patterns that are speeding up](https://github.com/ppy/osu/commit/56f66abf82b687d88e6fe83928d6dfa0f657b0a0) Assuming the same ratio difficulty, speeding up rhythms are a bit easier to play than slowing down ones ## [Reduce rhythm complexity sum if the final island is long](https://github.com/ppy/osu/commit/912d81cbfedee286b634c4bcb9c4e286d91a3d88) Currently due to how the rhythm complexity sum works rhythm difficulty gets applied to most of the object's island - historical decay isn't enough to counter difficulty carryover so we end up having non-zero rhythm difficulty on long consistent rhythm patterns (for example if a stream starts with an unusual ratio it will have non-zero rhythm difficulty regardless of its length, even if its hundreds of objects long). This applies a global difficulty reduction depending on the current object's island length. https://www.desmos.com/calculator/kvnpasbpt2 ## [Fix islands being initialised incorrectly if the rhythm section is longer than the historical cutoff](https://github.com/ppy/osu/commit/ddf0fe758b691ca6e2a157fe335a41c4048e7e9b) Due to the change above we now have to properly initialise islands at the start of the rhythm loop - currently if the object we're evaluating is a part of a >32 object consistent rhythm pattern (say a stream) it never actually gets its island properly initialised. It doesn't matter on the current system, but it does matter if we want to reduce complexity sum using island length as uninitialised island always has length of 1 so patterns that are >32 objects long stop getting their complexity reduced after the 32th object --------- Co-authored-by: James Wilson <tsunyoku@gmail.com>
This commit is contained in:
@@ -16,8 +16,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators.Speed
|
||||
{
|
||||
private const int history_time_max = 5 * 1000; // 5 seconds
|
||||
private const int history_objects_max = 32;
|
||||
private const double rhythm_overall_multiplier = 0.8;
|
||||
private const double rhythm_ratio_multiplier = 32.0;
|
||||
private const double rhythm_overall_multiplier = 0.95;
|
||||
private const double rhythm_ratio_multiplier = 26.0;
|
||||
|
||||
/// <summary>
|
||||
/// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current <see cref="OsuDifficultyHitObject"/>.
|
||||
@@ -70,6 +70,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators.Speed
|
||||
double prevDelta = Math.Max(prevObj.DeltaTime, 1e-7);
|
||||
double lastDelta = Math.Max(lastObj.DeltaTime, 1e-7);
|
||||
|
||||
// Make sure to always have the current island initialised - if we don't do it here it will only initialise on the next rhythm change
|
||||
if (island.Delta == int.MaxValue)
|
||||
island = new Island((int)currDelta, deltaDifferenceEpsilon);
|
||||
|
||||
// calculate how much current delta difference deserves a rhythm bonus
|
||||
// this function is meant to reduce rhythm bonus for deltas that are multiples of each other (i.e 100 and 200)
|
||||
double deltaDifference = Math.Max(prevDelta, currDelta) / Math.Min(prevDelta, currDelta);
|
||||
@@ -96,14 +100,17 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators.Speed
|
||||
effectiveRatio = Math.Min(sliderEffectiveRatio, effectiveRatio);
|
||||
}
|
||||
|
||||
bool isSpeedingUp = prevDelta > currDelta + deltaDifferenceEpsilon;
|
||||
|
||||
if (Math.Abs(prevDelta - currDelta) < deltaDifferenceEpsilon)
|
||||
{
|
||||
// island is still progressing
|
||||
island.AddDelta((int)currDelta);
|
||||
}
|
||||
|
||||
if (firstDeltaSwitch)
|
||||
{
|
||||
if (Math.Abs(prevDelta - currDelta) < deltaDifferenceEpsilon)
|
||||
{
|
||||
// island is still progressing
|
||||
island.AddDelta((int)currDelta);
|
||||
}
|
||||
else
|
||||
if (Math.Abs(prevDelta - currDelta) > deltaDifferenceEpsilon)
|
||||
{
|
||||
// bpm change is into slider, this is easy acc window
|
||||
if (currObj.BaseObject is Slider)
|
||||
@@ -122,6 +129,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators.Speed
|
||||
if (previousIsland.DeltaCount == island.DeltaCount)
|
||||
effectiveRatio *= 0.5;
|
||||
|
||||
if (isSpeedingUp)
|
||||
effectiveRatio *= 0.65;
|
||||
|
||||
var islandCount = islandCounts.FirstOrDefault(x => x.Island.Equals(island));
|
||||
|
||||
if (islandCount != default)
|
||||
@@ -140,7 +150,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators.Speed
|
||||
}
|
||||
else
|
||||
{
|
||||
islandCounts.Add((island, 1));
|
||||
if (island.DeltaCount > 0)
|
||||
{
|
||||
islandCounts.Add((island, 1));
|
||||
}
|
||||
}
|
||||
|
||||
// scale down the difficulty if the object is doubletappable
|
||||
@@ -182,6 +195,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators.Speed
|
||||
prevObj = currObj;
|
||||
}
|
||||
|
||||
// If the current island is long we don't want the sum to have as big of an effect
|
||||
rhythmComplexitySum *= DifficultyCalculationUtils.ReverseLerp(island.DeltaCount, 22, 3);
|
||||
|
||||
return Math.Sqrt(4 + rhythmComplexitySum * rhythm_overall_multiplier) / 2.0; // produces multiplier that can be applied to strain. range [1, infinity) (not really though);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user