mirror of
https://github.com/osukey/osukey.git
synced 2025-05-29 17:37:23 +09:00
Approximate amount of effective misses using combo
This commit is contained in:
parent
47b6fb05f7
commit
205d95e8c6
@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
public double OverallDifficulty { get; set; }
|
public double OverallDifficulty { get; set; }
|
||||||
public double DrainRate { get; set; }
|
public double DrainRate { get; set; }
|
||||||
public int HitCircleCount { get; set; }
|
public int HitCircleCount { get; set; }
|
||||||
|
public int SliderCount { get; set; }
|
||||||
public int SpinnerCount { get; set; }
|
public int SpinnerCount { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
maxCombo += beatmap.HitObjects.OfType<Slider>().Sum(s => s.NestedHitObjects.Count - 1);
|
maxCombo += beatmap.HitObjects.OfType<Slider>().Sum(s => s.NestedHitObjects.Count - 1);
|
||||||
|
|
||||||
int hitCirclesCount = beatmap.HitObjects.Count(h => h is HitCircle);
|
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);
|
int spinnerCount = beatmap.HitObjects.Count(h => h is Spinner);
|
||||||
|
|
||||||
return new OsuDifficultyAttributes
|
return new OsuDifficultyAttributes
|
||||||
@ -78,6 +79,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
DrainRate = drainRate,
|
DrainRate = drainRate,
|
||||||
MaxCombo = maxCombo,
|
MaxCombo = maxCombo,
|
||||||
HitCircleCount = hitCirclesCount,
|
HitCircleCount = hitCirclesCount,
|
||||||
|
SliderCount = sliderCount,
|
||||||
SpinnerCount = spinnerCount,
|
SpinnerCount = spinnerCount,
|
||||||
Skills = skills
|
Skills = skills
|
||||||
};
|
};
|
||||||
|
@ -25,6 +25,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
private int countMeh;
|
private int countMeh;
|
||||||
private int countMiss;
|
private int countMiss;
|
||||||
|
|
||||||
|
private int effectiveMissCount;
|
||||||
|
|
||||||
public OsuPerformanceCalculator(Ruleset ruleset, DifficultyAttributes attributes, ScoreInfo score)
|
public OsuPerformanceCalculator(Ruleset ruleset, DifficultyAttributes attributes, ScoreInfo score)
|
||||||
: base(ruleset, attributes, score)
|
: base(ruleset, attributes, score)
|
||||||
{
|
{
|
||||||
@ -39,19 +41,20 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
countOk = Score.Statistics.GetValueOrDefault(HitResult.Ok);
|
countOk = Score.Statistics.GetValueOrDefault(HitResult.Ok);
|
||||||
countMeh = Score.Statistics.GetValueOrDefault(HitResult.Meh);
|
countMeh = Score.Statistics.GetValueOrDefault(HitResult.Meh);
|
||||||
countMiss = Score.Statistics.GetValueOrDefault(HitResult.Miss);
|
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.
|
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.
|
// Custom multipliers for NoFail and SpunOut.
|
||||||
if (mods.Any(m => m is OsuModNoFail))
|
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))
|
if (mods.Any(m => m is OsuModSpunOut))
|
||||||
multiplier *= 1.0 - Math.Pow((double)Attributes.SpinnerCount / totalHits, 0.85);
|
multiplier *= 1.0 - Math.Pow((double)Attributes.SpinnerCount / totalHits, 0.85);
|
||||||
|
|
||||||
if (mods.Any(h => h is OsuModRelax))
|
if (mods.Any(h => h is OsuModRelax))
|
||||||
{
|
{
|
||||||
countMiss += countOk + countMeh;
|
effectiveMissCount += countOk + countMeh;
|
||||||
multiplier *= 0.6;
|
multiplier *= 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,8 +100,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
aimValue *= lengthBonus;
|
aimValue *= lengthBonus;
|
||||||
|
|
||||||
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
||||||
if (countMiss > 0)
|
if (effectiveMissCount > 0)
|
||||||
aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), countMiss);
|
aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), effectiveMissCount);
|
||||||
|
|
||||||
// Combo scaling.
|
// Combo scaling.
|
||||||
if (Attributes.MaxCombo > 0)
|
if (Attributes.MaxCombo > 0)
|
||||||
@ -115,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
double approachRateBonus = 1.0 + (0.03 + 0.37 * approachRateTotalHitsFactor) * approachRateFactor;
|
double approachRateBonus = 1.0 + (0.03 + 0.37 * approachRateTotalHitsFactor) * approachRateFactor;
|
||||||
|
|
||||||
if (mods.Any(m => m is OsuModBlinds))
|
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))
|
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.
|
// We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR.
|
||||||
@ -142,8 +145,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
speedValue *= lengthBonus;
|
speedValue *= lengthBonus;
|
||||||
|
|
||||||
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
||||||
if (countMiss > 0)
|
if (effectiveMissCount > 0)
|
||||||
speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), Math.Pow(countMiss, .875));
|
speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
|
||||||
|
|
||||||
// Combo scaling.
|
// Combo scaling.
|
||||||
if (Attributes.MaxCombo > 0)
|
if (Attributes.MaxCombo > 0)
|
||||||
@ -231,8 +234,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
flashlightValue *= 1.3;
|
flashlightValue *= 1.3;
|
||||||
|
|
||||||
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
||||||
if (countMiss > 0)
|
if (effectiveMissCount > 0)
|
||||||
flashlightValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), Math.Pow(countMiss, .875));
|
flashlightValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
|
||||||
|
|
||||||
// Combo scaling.
|
// Combo scaling.
|
||||||
if (Attributes.MaxCombo > 0)
|
if (Attributes.MaxCombo > 0)
|
||||||
@ -250,6 +253,23 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
return flashlightValue;
|
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 / scoreMaxCombo;
|
||||||
|
else
|
||||||
|
comboBasedMissCount = Math.Pow((Attributes.MaxCombo - scoreMaxCombo) / (0.1 * Attributes.SliderCount), 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.Max(countMiss, (int)Math.Floor(comboBasedMissCount));
|
||||||
|
}
|
||||||
|
|
||||||
private int totalHits => countGreat + countOk + countMeh + countMiss;
|
private int totalHits => countGreat + countOk + countMeh + countMiss;
|
||||||
private int totalSuccessfulHits => countGreat + countOk + countMeh;
|
private int totalSuccessfulHits => countGreat + countOk + countMeh;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user