Skip to content

Commit

Permalink
Merge pull request #15086 from stanriders/effective-miss-count
Browse files Browse the repository at this point in the history
Approximate amount of effective misses using combo
  • Loading branch information
smoogipoo authored Oct 18, 2021
2 parents a9ba4e5 + 80827b7 commit 43c2e9b
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class OsuDifficultyAttributes : DifficultyAttributes
public double OverallDifficulty { get; set; }
public double DrainRate { get; set; }
public int HitCircleCount { get; set; }
public int SliderCount { get; set; }
public int SpinnerCount { get; set; }
}
}
2 changes: 2 additions & 0 deletions osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat
maxCombo += beatmap.HitObjects.OfType<Slider>().Sum(s => s.NestedHitObjects.Count - 1);

int hitCirclesCount = beatmap.HitObjects.Count(h => h is HitCircle);
int sliderCount = beatmap.HitObjects.Count(h => h is Slider);
int spinnerCount = beatmap.HitObjects.Count(h => h is Spinner);

return new OsuDifficultyAttributes
Expand All @@ -78,6 +79,7 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat
DrainRate = drainRate,
MaxCombo = maxCombo,
HitCircleCount = hitCirclesCount,
SliderCount = sliderCount,
SpinnerCount = spinnerCount,
Skills = skills
};
Expand Down
39 changes: 30 additions & 9 deletions osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public class OsuPerformanceCalculator : PerformanceCalculator
private int countMeh;
private int countMiss;

private int effectiveMissCount;

public OsuPerformanceCalculator(Ruleset ruleset, DifficultyAttributes attributes, ScoreInfo score)
: base(ruleset, attributes, score)
{
Expand All @@ -39,19 +41,20 @@ public override double Calculate(Dictionary<string, double> categoryRatings = nu
countOk = Score.Statistics.GetValueOrDefault(HitResult.Ok);
countMeh = Score.Statistics.GetValueOrDefault(HitResult.Meh);
countMiss = Score.Statistics.GetValueOrDefault(HitResult.Miss);
effectiveMissCount = calculateEffectiveMissCount();

double multiplier = 1.12; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things.

// Custom multipliers for NoFail and SpunOut.
if (mods.Any(m => m is OsuModNoFail))
multiplier *= Math.Max(0.90, 1.0 - 0.02 * countMiss);
multiplier *= Math.Max(0.90, 1.0 - 0.02 * effectiveMissCount);

if (mods.Any(m => m is OsuModSpunOut))
multiplier *= 1.0 - Math.Pow((double)Attributes.SpinnerCount / totalHits, 0.85);

if (mods.Any(h => h is OsuModRelax))
{
countMiss += countOk + countMeh;
effectiveMissCount += countOk + countMeh;
multiplier *= 0.6;
}

Expand Down Expand Up @@ -97,8 +100,8 @@ private double computeAimValue()
aimValue *= lengthBonus;

// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (countMiss > 0)
aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), countMiss);
if (effectiveMissCount > 0)
aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), effectiveMissCount);

// Combo scaling.
if (Attributes.MaxCombo > 0)
Expand All @@ -115,7 +118,7 @@ private double computeAimValue()
double approachRateBonus = 1.0 + (0.03 + 0.37 * approachRateTotalHitsFactor) * approachRateFactor;

if (mods.Any(m => m is OsuModBlinds))
aimValue *= 1.3 + (totalHits * (0.0016 / (1 + 2 * countMiss)) * Math.Pow(accuracy, 16)) * (1 - 0.003 * Attributes.DrainRate * Attributes.DrainRate);
aimValue *= 1.3 + (totalHits * (0.0016 / (1 + 2 * effectiveMissCount)) * Math.Pow(accuracy, 16)) * (1 - 0.003 * Attributes.DrainRate * Attributes.DrainRate);
else if (mods.Any(h => h is OsuModHidden))
{
// We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR.
Expand All @@ -142,8 +145,8 @@ private double computeSpeedValue()
speedValue *= lengthBonus;

// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (countMiss > 0)
speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), Math.Pow(countMiss, .875));
if (effectiveMissCount > 0)
speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));

// Combo scaling.
if (Attributes.MaxCombo > 0)
Expand Down Expand Up @@ -231,8 +234,8 @@ private double computeFlashlightValue()
flashlightValue *= 1.3;

// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (countMiss > 0)
flashlightValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), Math.Pow(countMiss, .875));
if (effectiveMissCount > 0)
flashlightValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));

// Combo scaling.
if (Attributes.MaxCombo > 0)
Expand All @@ -250,6 +253,24 @@ private double computeFlashlightValue()
return flashlightValue;
}

private int calculateEffectiveMissCount()
{
// guess the number of misses + slider breaks from combo
double comboBasedMissCount = 0.0;

if (Attributes.SliderCount > 0)
{
double fullComboThreshold = Attributes.MaxCombo - 0.1 * Attributes.SliderCount;
if (scoreMaxCombo < fullComboThreshold)
comboBasedMissCount = fullComboThreshold / Math.Max(1.0, scoreMaxCombo);
}

// we're clamping misscount because since its derived from combo it can be higher than total hits and that breaks some calculations
comboBasedMissCount = Math.Min(comboBasedMissCount, totalHits);

return Math.Max(countMiss, (int)Math.Floor(comboBasedMissCount));
}

private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh;
}
Expand Down

0 comments on commit 43c2e9b

Please sign in to comment.