Skip to content

Commit f8bc6aa

Browse files
stanriderstsunyokumazziebot
authored
2026 Q2 PP/SR update (#309)
* Fix `ObjectDifficultyValuesContainer` using wrong FL eval param * Add per-object difficulty visualization to `StrainVisualizer` (#296) * Simplify ExtendedDifficultyCalculators usage * Add per-object difficulty visualization to StrainVisualizer * Split `getStrainLists` * fix: speed difficulty eval no longer takes mods as an argument (#297) * Fix object inspection * Add new osu inspector fields * Update object inspector fields * Update evaluator imports * Update extended difficulty calculators (#304) * Remove `AngularVelocity` inspector value * Fix `LegacyBeatmapMetadataDecoder` * Use `ScoreMultiplierCalculator` in `AdjustManiaScore` * Update in line with pp-dev changes * Update packages * `using`s --------- Co-authored-by: James Wilson <tsunyoku@gmail.com> Co-authored-by: mazzie <mazziechai@gmail.com>
1 parent d82cf2a commit f8bc6aa

11 files changed

Lines changed: 197 additions & 132 deletions

PerformanceCalculator/PerformanceCalculator.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
<ItemGroup>
88
<PackageReference Include="Alba.CsConsoleFormat" Version="1.0.0" />
99
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="5.0.1" />
10-
<PackageReference Include="ppy.osu.Game" Version="2026.317.0" />
11-
<PackageReference Include="ppy.osu.Game.Rulesets.Osu" Version="2026.317.0" />
12-
<PackageReference Include="ppy.osu.Game.Rulesets.Taiko" Version="2026.317.0" />
13-
<PackageReference Include="ppy.osu.Game.Rulesets.Catch" Version="2026.317.0" />
14-
<PackageReference Include="ppy.osu.Game.Rulesets.Mania" Version="2026.317.0" />
10+
<PackageReference Include="ppy.osu.Game" Version="2026.702.1" />
11+
<PackageReference Include="ppy.osu.Game.Rulesets.Osu" Version="2026.702.1" />
12+
<PackageReference Include="ppy.osu.Game.Rulesets.Taiko" Version="2026.702.1" />
13+
<PackageReference Include="ppy.osu.Game.Rulesets.Catch" Version="2026.702.1" />
14+
<PackageReference Include="ppy.osu.Game.Rulesets.Mania" Version="2026.702.1" />
1515
</ItemGroup>
1616
</Project>

PerformanceCalculatorGUI/Components/ExtendedOsuFileSelector.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ namespace PerformanceCalculatorGUI.Components
1212
{
1313
public class LegacyBeatmapMetadataDecoder : LegacyBeatmapDecoder
1414
{
15-
protected override void ParseLine(Beatmap beatmap, Section section, string line)
15+
protected override void ParseLine(Beatmap beatmap, Section section, string line, bool isPrimaryStream)
1616
{
1717
// early out to only parse relevant data
1818
if (section != Section.Metadata && section != Section.General)
1919
return;
2020

21-
base.ParseLine(beatmap, section, line);
21+
base.ParseLine(beatmap, section, line, isPrimaryStream);
2222
}
2323
}
2424

PerformanceCalculatorGUI/ExtendedCatchDifficultyCalculator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ public ExtendedCatchDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap b
2525
public Skill[] GetSkills() => skills;
2626
public DifficultyHitObject[] GetDifficultyHitObjects() => difficultyHitObjects;
2727

28-
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate)
28+
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods)
2929
{
30-
difficultyHitObjects = base.CreateDifficultyHitObjects(beatmap, clockRate).ToArray();
30+
difficultyHitObjects = base.CreateDifficultyHitObjects(beatmap, mods).ToArray();
3131
return difficultyHitObjects;
3232
}
3333

34-
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
34+
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods)
3535
{
36-
skills = base.CreateSkills(beatmap, mods, clockRate);
36+
skills = base.CreateSkills(beatmap, mods);
3737
return skills;
3838
}
3939
}

PerformanceCalculatorGUI/ExtendedManiaDifficultyCalculator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ public ExtendedManiaDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap b
2525
public Skill[] GetSkills() => skills;
2626
public DifficultyHitObject[] GetDifficultyHitObjects() => difficultyHitObjects;
2727

28-
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate)
28+
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods)
2929
{
30-
difficultyHitObjects = base.CreateDifficultyHitObjects(beatmap, clockRate).ToArray();
30+
difficultyHitObjects = base.CreateDifficultyHitObjects(beatmap, mods).ToArray();
3131
return difficultyHitObjects;
3232
}
3333

34-
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
34+
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods)
3535
{
36-
skills = base.CreateSkills(beatmap, mods, clockRate);
36+
skills = base.CreateSkills(beatmap, mods);
3737
return skills;
3838
}
3939
}

PerformanceCalculatorGUI/ExtendedOsuDifficultyCalculator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ public ExtendedOsuDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap bea
2525
public Skill[] GetSkills() => skills;
2626
public DifficultyHitObject[] GetDifficultyHitObjects() => difficultyHitObjects;
2727

28-
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate)
28+
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods)
2929
{
30-
difficultyHitObjects = base.CreateDifficultyHitObjects(beatmap, clockRate).ToArray();
30+
difficultyHitObjects = base.CreateDifficultyHitObjects(beatmap, mods).ToArray();
3131
return difficultyHitObjects;
3232
}
3333

34-
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
34+
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods)
3535
{
36-
skills = base.CreateSkills(beatmap, mods, clockRate);
36+
skills = base.CreateSkills(beatmap, mods);
3737
return skills;
3838
}
3939
}

PerformanceCalculatorGUI/ExtendedTaikoDifficultyCalculator.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ public ExtendedTaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap b
2525
public Skill[] GetSkills() => skills;
2626
public DifficultyHitObject[] GetDifficultyHitObjects() => difficultyHitObjects;
2727

28-
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate)
28+
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, Mod[] mods)
2929
{
30-
difficultyHitObjects = base.CreateDifficultyHitObjects(beatmap, clockRate).ToArray();
30+
difficultyHitObjects = base.CreateDifficultyHitObjects(beatmap, mods).ToArray();
3131
return difficultyHitObjects;
3232
}
3333

34-
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
34+
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods)
3535
{
36-
skills = base.CreateSkills(beatmap, mods, clockRate);
36+
skills = base.CreateSkills(beatmap, mods);
3737
return skills;
3838
}
3939
}

PerformanceCalculatorGUI/PerformanceCalculatorGUI.csproj

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
<TargetFramework>net8.0</TargetFramework>
66
</PropertyGroup>
77
<ItemGroup>
8-
<PackageReference Include="ppy.osu.Game" Version="2026.317.0" />
9-
<PackageReference Include="ppy.osu.Game.Rulesets.Osu" Version="2026.317.0" />
10-
<PackageReference Include="ppy.osu.Game.Rulesets.Taiko" Version="2026.317.0" />
11-
<PackageReference Include="ppy.osu.Game.Rulesets.Catch" Version="2026.317.0" />
12-
<PackageReference Include="ppy.osu.Game.Rulesets.Mania" Version="2026.317.0" />
8+
<PackageReference Include="ppy.osu.Game" Version="2026.702.1" />
9+
<PackageReference Include="ppy.osu.Game.Rulesets.Osu" Version="2026.702.1" />
10+
<PackageReference Include="ppy.osu.Game.Rulesets.Taiko" Version="2026.702.1" />
11+
<PackageReference Include="ppy.osu.Game.Rulesets.Catch" Version="2026.702.1" />
12+
<PackageReference Include="ppy.osu.Game.Rulesets.Mania" Version="2026.702.1" />
1313
</ItemGroup>
1414
</Project>

PerformanceCalculatorGUI/RulesetHelper.cs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,14 @@ public static Ruleset GetRulesetFromLegacyID(int id)
4646
};
4747
}
4848

49-
public static int AdjustManiaScore(int score, IReadOnlyList<Mod> mods)
49+
public static int AdjustManiaScore(int score, IReadOnlyList<Mod> mods, Ruleset ruleset)
5050
{
51-
if (score != 1000000) return score;
51+
if (score != 1000000)
52+
return score;
5253

53-
double scoreMultiplier = 1;
54+
var scoreMultiplierCalculator = ruleset.CreateScoreMultiplierCalculator(new ScoreMultiplierContext(new BeatmapDifficulty())); // we don't really care about the beatmap difficulty
5455

55-
// Cap score depending on difficulty adjustment mods (matters for mania).
56-
foreach (var mod in mods)
57-
{
58-
if (mod.Type == ModType.DifficultyReduction)
59-
scoreMultiplier *= mod.ScoreMultiplier;
60-
}
61-
62-
return (int)Math.Round(1000000 * scoreMultiplier);
56+
return (int)Math.Round(1000000 * scoreMultiplierCalculator.CalculateFor(mods));
6357
}
6458

6559
public static Dictionary<HitResult, int> GenerateHitResultsForRuleset(RulesetInfo ruleset, double accuracy, IBeatmap beatmap, Mod[] mods, int countMiss, int? countMeh, int? countGood, int? countLargeTickMisses, int? countSliderTailMisses)

PerformanceCalculatorGUI/Screens/ObjectInspection/ObjectDifficultyValuesContainer.cs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
using osu.Game.Rulesets.Difficulty.Preprocessing;
1919
using osu.Game.Rulesets.Mods;
2020
using osu.Game.Rulesets.Osu.Difficulty.Evaluators;
21+
using osu.Game.Rulesets.Osu.Difficulty.Evaluators.Aim;
22+
using osu.Game.Rulesets.Osu.Difficulty.Evaluators.Speed;
2123
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
2224
using osu.Game.Rulesets.Osu.Objects;
23-
using osu.Game.Rulesets.Scoring;
2425
using osu.Game.Rulesets.Taiko.Difficulty.Evaluators;
2526
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
2627
using osu.Game.Rulesets.Taiko.Objects;
@@ -134,16 +135,22 @@ private void drawOsuValues(OsuDifficultyHitObject hitObject)
134135
new ObjectInspectorDifficultyValue("Position", (hitObject.BaseObject as OsuHitObject)!.StackedPosition),
135136
new ObjectInspectorDifficultyValue("Delta Time", hitObject.DeltaTime),
136137
new ObjectInspectorDifficultyValue("Adjusted Delta Time", hitObject.AdjustedDeltaTime),
137-
new ObjectInspectorDifficultyValue("Doubletapness", hitObject.GetDoubletapness((OsuDifficultyHitObject)hitObject.Next(0))),
138+
new ObjectInspectorDifficultyValue("Last Obj End Delta Time", hitObject.LastObjectEndDeltaTime),
139+
new ObjectInspectorDifficultyValue("Doubletap Feasibility", hitObject.CalculateDoubleTapFeasibility((OsuDifficultyHitObject)hitObject.Next())),
140+
new ObjectInspectorDifficultyValue("Jump Distance", hitObject.JumpDistance),
138141
new ObjectInspectorDifficultyValue("Lazy Jump Dist", hitObject.LazyJumpDistance),
139142
new ObjectInspectorDifficultyValue("Min Jump Dist", hitObject.MinimumJumpDistance),
140143
new ObjectInspectorDifficultyValue("Min Jump Time", hitObject.MinimumJumpTime),
141144

142-
new ObjectInspectorDifficultyValue("Aim Difficulty", AimEvaluator.EvaluateDifficultyOf(hitObject, true)),
143-
new ObjectInspectorDifficultyValue("Aim Difficulty (w/o sliders)", AimEvaluator.EvaluateDifficultyOf(hitObject, false)),
144-
new ObjectInspectorDifficultyValue("Speed Difficulty", SpeedEvaluator.EvaluateDifficultyOf(hitObject, appliedMods.Value)),
145-
new ObjectInspectorDifficultyValue("Rhythm Diff", osu.Game.Rulesets.Osu.Difficulty.Evaluators.RhythmEvaluator.EvaluateDifficultyOf(hitObject)),
146-
new ObjectInspectorDifficultyValue(hidden ? "FLHD Difficulty" : "Flashlight Diff", FlashlightEvaluator.EvaluateDifficultyOf(hitObject, hidden)),
145+
new ObjectInspectorDifficultyValue("Snap Aim Difficulty", SnapAimEvaluator.EvaluateDifficultyOf(hitObject, true)),
146+
new ObjectInspectorDifficultyValue("Snap Aim Difficulty (w/o sliders)", SnapAimEvaluator.EvaluateDifficultyOf(hitObject, false)),
147+
new ObjectInspectorDifficultyValue("Flow Aim Difficulty", FlowAimEvaluator.EvaluateDifficultyOf(hitObject, true)),
148+
new ObjectInspectorDifficultyValue("Flow Aim Difficulty (w/o sliders)", FlowAimEvaluator.EvaluateDifficultyOf(hitObject, false)),
149+
new ObjectInspectorDifficultyValue("Agility Difficulty", AgilityEvaluator.EvaluateDifficultyOf(hitObject)),
150+
new ObjectInspectorDifficultyValue("Speed Difficulty", SpeedEvaluator.EvaluateDifficultyOf(hitObject)),
151+
new ObjectInspectorDifficultyValue("Rhythm Difficulty", osu.Game.Rulesets.Osu.Difficulty.Evaluators.Speed.RhythmEvaluator.EvaluateDifficultyOf(hitObject)),
152+
new ObjectInspectorDifficultyValue("Reading Difficulty", osu.Game.Rulesets.Osu.Difficulty.Evaluators.ReadingEvaluator.EvaluateDifficultyOf(hitObject, hidden)),
153+
new ObjectInspectorDifficultyValue(hidden ? "FLHD Difficulty" : "Flashlight Diff", FlashlightEvaluator.EvaluateDifficultyOf(hitObject, appliedMods.Value)),
147154
});
148155

149156
if (hitObject.Angle is not null)
@@ -173,17 +180,14 @@ private void drawOsuValues(OsuDifficultyHitObject hitObject)
173180

174181
private void drawTaikoValues(TaikoDifficultyHitObject hitObject)
175182
{
176-
double rhythmDifficulty =
177-
osu.Game.Rulesets.Taiko.Difficulty.Evaluators.RhythmEvaluator.EvaluateDifficultyOf(hitObject, 2 * hitObject.BaseObject.HitWindows.WindowFor(HitResult.Great) / track.Rate);
178-
179183
flowContainer.AddRange(new[]
180184
{
181185
new ObjectInspectorDifficultyValue("Delta Time", hitObject.DeltaTime),
182186
new ObjectInspectorDifficultyValue("Effective BPM", hitObject.EffectiveBPM),
183187
new ObjectInspectorDifficultyValue("Rhythm Ratio", hitObject.RhythmData.Ratio),
184188
new ObjectInspectorDifficultyValue("Colour Difficulty", ColourEvaluator.EvaluateDifficultyOf(hitObject)),
185189
new ObjectInspectorDifficultyValue("Stamina Difficulty", StaminaEvaluator.EvaluateDifficultyOf(hitObject)),
186-
new ObjectInspectorDifficultyValue("Rhythm Difficulty", rhythmDifficulty),
190+
new ObjectInspectorDifficultyValue("Rhythm Difficulty", osu.Game.Rulesets.Taiko.Difficulty.Evaluators.RhythmEvaluator.EvaluateDifficultyOf(hitObject)),
187191
});
188192

189193
if (hitObject.BaseObject is Hit hit)
@@ -207,9 +211,7 @@ private void drawCatchValues(CatchDifficultyHitObject hitObject)
207211
new ObjectInspectorDifficultyValue("Last Player Position", hitObject.LastPlayerPosition),
208212
new ObjectInspectorDifficultyValue("Distance Moved", hitObject.DistanceMoved),
209213
new ObjectInspectorDifficultyValue("Exact Distance Moved", hitObject.ExactDistanceMoved),
210-
211-
// see https://github.com/ppy/osu/blob/a08f7327b11977f1de57b8a177bf26918ebfacda/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs#L36
212-
new ObjectInspectorDifficultyValue("Movement Difficulty", MovementEvaluator.EvaluateDifficultyOf(hitObject, track.Rate)),
214+
new ObjectInspectorDifficultyValue("Movement Difficulty", MovementEvaluator.EvaluateDifficultyOf(hitObject)),
213215
});
214216
}
215217
}

0 commit comments

Comments
 (0)