1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-30 21:13:22 +08:00

scale misscount by proportion of difficult sliders

This commit is contained in:
danielthirtle 2024-12-22 04:03:52 +13:00
parent d3d111de7d
commit e0019c46a5
6 changed files with 37 additions and 2 deletions

View File

@ -45,6 +45,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty
/// </summary>
[JsonProperty("slider_factor")]
public double SliderFactor { get; set; }
[JsonProperty("aim_top_weighted_slider_factor")]
public double AimTopWeightedSliderFactor { get; set; }
[JsonProperty("speed_top_weighted_slider_factor")]
public double SpeedTopWeightedSliderFactor { get; set; }
[JsonProperty("aim_difficult_strain_count")]
public double AimDifficultStrainCount { get; set; }

View File

@ -50,6 +50,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountTopWeightedStrains();
double speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountTopWeightedStrains();
(double hitCircles, double sliders) aimTypedDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountTypedTopWeightedStrains();
(double hitCircles, double sliders) speedTypedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountTypedTopWeightedStrains();
double aimTopWeightedSliderFactor = aimTypedDifficultyStrainCount.sliders / aimTypedDifficultyStrainCount.hitCircles;
double speedTopWeightedSliderFactor = speedTypedDifficultyStrainCount.sliders / speedTypedDifficultyStrainCount.hitCircles;
if (mods.Any(m => m is OsuModTouchDevice))
{
@ -105,6 +110,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
SliderFactor = sliderFactor,
AimDifficultStrainCount = aimDifficultyStrainCount,
SpeedDifficultStrainCount = speedDifficultyStrainCount,
AimTopWeightedSliderFactor = aimTopWeightedSliderFactor,
SpeedTopWeightedSliderFactor = speedTopWeightedSliderFactor,
ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5,
OverallDifficulty = (80 - hitWindowGreat) / 6,
DrainRate = drainRate,

View File

@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
aimValue *= lengthBonus;
if (effectiveMissCount > 0)
aimValue *= calculateMissPenalty(effectiveMissCount, attributes.AimDifficultStrainCount);
aimValue *= calculateMissPenalty(effectiveMissCount * (1 + (usingClassicSliderAccuracy ? attributes.AimTopWeightedSliderFactor : 0)), attributes.AimDifficultStrainCount);
double approachRateFactor = 0.0;
if (attributes.ApproachRate > 10.33)
@ -206,7 +206,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
speedValue *= lengthBonus;
if (effectiveMissCount > 0)
speedValue *= calculateMissPenalty(effectiveMissCount, attributes.SpeedDifficultStrainCount);
speedValue *= calculateMissPenalty(effectiveMissCount * (1 + (usingClassicSliderAccuracy ? attributes.SpeedTopWeightedSliderFactor : 0)), attributes.SpeedDifficultStrainCount);
double approachRateFactor = 0.0;
if (attributes.ApproachRate > 10.33)

View File

@ -5,6 +5,7 @@ using System;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Difficulty.Evaluators;
using osu.Game.Rulesets.Osu.Objects;
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{
@ -35,6 +36,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
currentStrain *= strainDecay(current.DeltaTime);
currentStrain += AimEvaluator.EvaluateDifficultyOf(current, withSliders) * skillMultiplier;
typedObjectStrains.Add((currentStrain, current.BaseObject is Slider));
return currentStrain;
}
}

View File

@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
/// The baseline multiplier applied to the section with the biggest strain.
/// </summary>
protected virtual double ReducedStrainBaseline => 0.75;
protected List<(double difficulty, bool isSlider)> typedObjectStrains = new List<(double, bool)>();
protected OsuStrainSkill(Mod[] mods)
: base(mods)
@ -56,6 +57,24 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return difficulty;
}
public (double hitCircles, double sliders) CountTypedTopWeightedStrains()
{
if (typedObjectStrains.Count == 0)
return (0.0, 0.0);
double consistentTopStrain = DifficultyValue() / 10; // What would the top strain be if all strain values were identical
List<double> sliderStrains = typedObjectStrains.Where(typedObjectStrain => typedObjectStrain.isSlider).Select(typedObjectStrain => typedObjectStrain.difficulty).ToList();
List<double> circleStrains = typedObjectStrains.Where(typedObjectStrain => !typedObjectStrain.isSlider).Select(typedObjectStrain => typedObjectStrain.difficulty).ToList();
if (consistentTopStrain == 0)
return (circleStrains.Count, sliderStrains.Count);
// Use a weighted sum of all strains. Constants are arbitrary and give nice values
double sliderObjects = sliderStrains.Sum(s => 1.1 / (1 + Math.Exp(-10 * (s / consistentTopStrain - 0.88))));
double circleObjects = circleStrains.Sum(s => 1.1 / (1 + Math.Exp(-10 * (s / consistentTopStrain - 0.88))));
return (circleObjects, sliderObjects);
}
public static double DifficultyToPerformance(double difficulty) => Math.Pow(5.0 * Math.Max(1.0, difficulty / 0.0675) - 4.0, 3.0) / 100000.0;
}

View File

@ -6,6 +6,7 @@ using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Difficulty.Evaluators;
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
using osu.Game.Rulesets.Osu.Objects;
using System.Linq;
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
@ -40,6 +41,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
currentRhythm = RhythmEvaluator.EvaluateDifficultyOf(current);
double totalStrain = currentStrain * currentRhythm;
typedObjectStrains.Add((totalStrain, current.BaseObject is Slider));
return totalStrain;
}