1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-31 01:00:51 +08:00

osu!taiko penalty for frequent rhythm changes with long gaps (#37200)

Co-authored-by: Jay Lawton <jaime@merkids.com>
Co-authored-by: James Wilson <tsunyoku@gmail.com>
This commit is contained in:
Eloise
2026-05-13 20:31:15 +01:00
committed by GitHub
Unverified
parent c5871069cd
commit a84f5a76c8
2 changed files with 30 additions and 2 deletions
@@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
double sameRhythm = 0;
double samePattern = 0;
double intervalPenalty = 0;
double gapPenalty = 0;
double hitWindow = hitObject.HitWindow(HitResult.Great);
@@ -36,12 +37,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
{
sameRhythm += 10.0 * evaluateDifficultyOf(rhythmData.SameRhythmGroupedHitObjects, hitWindow);
intervalPenalty = repeatedIntervalPenalty(rhythmData.SameRhythmGroupedHitObjects, hitWindow);
gapPenalty = longGapPenalty(rhythmData.SameRhythmGroupedHitObjects.Previous);
}
if (rhythmData.SamePatternsGroupedHitObjects?.FirstHitObject == hitObject) // Difficulty for SamePatternsGroupedHitObjects
samePattern += 1.15 * ratioDifficulty(rhythmData.SamePatternsGroupedHitObjects.IntervalRatio);
difficulty += Math.Max(sameRhythm, samePattern) * intervalPenalty;
difficulty += Math.Max(sameRhythm, samePattern) * intervalPenalty * gapPenalty;
return difficulty;
}
@@ -125,6 +127,32 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
}
}
/// <summary>
/// Frequent rhythm changes containing long gaps (i.e. 1/4 + 1/6 with 1/2 gaps) award more difficulty than expected.
/// Due to limitations of the current rhythm evaluation, these cases are targeted and penalised.
/// The previous hit object grouping is used as often the rhythm change *two* rhythms after a long gap awards the unexpected difficulty.
/// </summary>
private static double longGapPenalty(SameRhythmHitObjectGrouping? previous)
{
if (previous == null)
return 1.0;
double gapInterval = previous.FirstHitObject.DeltaTime;
double rhythmInterval = previous.HitObjectInterval ?? gapInterval;
double rhythmLength = previous.HitObjects.Count;
// The ratio of the gap before this rhythm to the rhythm itself.
double gapRatio = gapInterval / Math.Max(rhythmInterval, 1);
// The gap ratio normalised to represent if the gap is long.
double gapFactor = DifficultyCalculationUtils.Logistic(gapRatio, 1.75, 20);
// The length in objects of this rhythm normalised to represent if the rhythm change is frequent enough to be penalised.
double lengthFactor = DifficultyCalculationUtils.ReverseLerp(rhythmLength, 8, 2);
return 1.0 - 0.75 * gapFactor * lengthFactor;
}
/// <summary>
/// Calculates the difficulty of a given ratio using a combination of periodic penalties and bonuses.
/// </summary>
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
public class TaikoDifficultyCalculator : DifficultyCalculator
{
private const double difficulty_multiplier = 0.084375;
private const double rhythm_skill_multiplier = 0.750 * difficulty_multiplier;
private const double rhythm_skill_multiplier = 0.770 * difficulty_multiplier;
private const double reading_skill_multiplier = 0.100 * difficulty_multiplier;
private const double colour_skill_multiplier = 0.375 * difficulty_multiplier;
private const double stamina_skill_multiplier = 0.445 * difficulty_multiplier;