1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-06 06:17:23 +08:00

Unify to use double in performance calculators.

This commit is contained in:
Huo Yaoyuan 2019-11-26 18:34:23 +08:00
parent 3fb2f6e320
commit 9425e80a5d
3 changed files with 56 additions and 58 deletions

View File

@ -47,55 +47,53 @@ namespace osu.Game.Rulesets.Catch.Difficulty
return 0;
// We are heavily relying on aim in catch the beat
double value = Math.Pow(5.0f * Math.Max(1.0f, Attributes.StarRating / 0.0049f) - 4.0f, 2.0f) / 100000.0f;
double value = Math.Pow(5.0 * Math.Max(1.0, Attributes.StarRating / 0.0049) - 4.0, 2.0) / 100000.0;
// Longer maps are worth more. "Longer" means how many hits there are which can contribute to combo
int numTotalHits = totalComboHits();
// Longer maps are worth more
float lengthBonus =
0.95f + 0.4f * Math.Min(1.0f, numTotalHits / 3000.0f) +
(numTotalHits > 3000 ? MathF.Log10(numTotalHits / 3000.0f) * 0.5f : 0.0f);
double lengthBonus =
0.95 + 0.4 * Math.Min(1.0, numTotalHits / 3000.0) +
(numTotalHits > 3000 ? Math.Log10(numTotalHits / 3000.0) * 0.5 : 0.0);
// Longer maps are worth more
value *= lengthBonus;
// Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available
value *= Math.Pow(0.97f, misses);
value *= Math.Pow(0.97, misses);
// Combo scaling
float beatmapMaxCombo = Attributes.MaxCombo;
if (beatmapMaxCombo > 0)
value *= Math.Min(Math.Pow(Attributes.MaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f);
if (Attributes.MaxCombo > 0)
value *= Math.Min(Math.Pow(Attributes.MaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0);
float approachRate = (float)Attributes.ApproachRate;
float approachRateFactor = 1.0f;
if (approachRate > 9.0f)
approachRateFactor += 0.1f * (approachRate - 9.0f); // 10% for each AR above 9
else if (approachRate < 8.0f)
approachRateFactor += 0.025f * (8.0f - approachRate); // 2.5% for each AR below 8
double approachRateFactor = 1.0;
if (Attributes.ApproachRate > 9.0)
approachRateFactor += 0.1 * (Attributes.ApproachRate - 9.0); // 10% for each AR above 9
else if (Attributes.ApproachRate < 8.0)
approachRateFactor += 0.025 * (8.0 - Attributes.ApproachRate); // 2.5% for each AR below 8
value *= approachRateFactor;
if (mods.Any(m => m is ModHidden))
// Hiddens gives nothing on max approach rate, and more the lower it is
value *= 1.05f + 0.075f * (10.0f - Math.Min(10.0f, approachRate)); // 7.5% for each AR below 10
value *= 1.05 + 0.075 * (10.0 - Math.Min(10.0, Attributes.ApproachRate)); // 7.5% for each AR below 10
if (mods.Any(m => m is ModFlashlight))
// Apply length bonus again if flashlight is on simply because it becomes a lot harder on longer maps.
value *= 1.35f * lengthBonus;
value *= 1.35 * lengthBonus;
// Scale the aim value with accuracy _slightly_
value *= Math.Pow(accuracy(), 5.5f);
value *= Math.Pow(accuracy(), 5.5);
// Custom multipliers for NoFail. SpunOut is not applicable.
if (mods.Any(m => m is ModNoFail))
value *= 0.90f;
value *= 0.90;
return value;
}
private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0f, 1f);
private float accuracy() => totalHits() == 0 ? 0 : Math.Clamp((float)totalSuccessfulHits() / totalHits(), 0, 1);
private int totalHits() => tinyTicksHit + ticksHit + fruitsHit + misses + tinyTicksMissed;
private int totalSuccessfulHits() => tinyTicksHit + ticksHit + fruitsHit;
private int totalComboHits() => misses + ticksHit + fruitsHit;

View File

@ -55,22 +55,22 @@ namespace osu.Game.Rulesets.Osu.Difficulty
return 0;
// Custom multipliers for NoFail and SpunOut.
double multiplier = 1.12f; // 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
if (mods.Any(m => m is OsuModNoFail))
multiplier *= 0.90f;
multiplier *= 0.90;
if (mods.Any(m => m is OsuModSpunOut))
multiplier *= 0.95f;
multiplier *= 0.95;
double aimValue = computeAimValue();
double speedValue = computeSpeedValue();
double accuracyValue = computeAccuracyValue();
double totalValue =
Math.Pow(
Math.Pow(aimValue, 1.1f) +
Math.Pow(speedValue, 1.1f) +
Math.Pow(accuracyValue, 1.1f), 1.0f / 1.1f
Math.Pow(aimValue, 1.1) +
Math.Pow(speedValue, 1.1) +
Math.Pow(accuracyValue, 1.1), 1.0 / 1.1
) * multiplier;
if (categoryRatings != null)
@ -93,82 +93,82 @@ namespace osu.Game.Rulesets.Osu.Difficulty
if (mods.Any(m => m is OsuModTouchDevice))
rawAim = Math.Pow(rawAim, 0.8);
double aimValue = Math.Pow(5.0f * Math.Max(1.0f, rawAim / 0.0675f) - 4.0f, 3.0f) / 100000.0f;
double aimValue = Math.Pow(5.0 * Math.Max(1.0, rawAim / 0.0675) - 4.0, 3.0) / 100000.0;
// Longer maps are worth more
double lengthBonus = 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f);
double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
aimValue *= lengthBonus;
// Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available
aimValue *= Math.Pow(0.97f, countMiss);
aimValue *= Math.Pow(0.97, countMiss);
// Combo scaling
if (beatmapMaxCombo > 0)
aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f);
aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(beatmapMaxCombo, 0.8), 1.0);
double approachRateFactor = 1.0f;
double approachRateFactor = 1.0;
if (Attributes.ApproachRate > 10.33f)
approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f);
else if (Attributes.ApproachRate < 8.0f)
if (Attributes.ApproachRate > 10.33)
approachRateFactor += 0.3 * (Attributes.ApproachRate - 10.33);
else if (Attributes.ApproachRate < 8.0)
{
approachRateFactor += 0.01f * (8.0f - Attributes.ApproachRate);
approachRateFactor += 0.01 * (8.0 - Attributes.ApproachRate);
}
aimValue *= approachRateFactor;
// We want to give more reward for lower AR when it comes to aim and HD. This nerfs high AR and buffs lower AR.
if (mods.Any(h => h is OsuModHidden))
aimValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate);
aimValue *= 1.0 + 0.04 * (12.0 - Attributes.ApproachRate);
if (mods.Any(h => h is OsuModFlashlight))
{
// Apply object-based bonus for flashlight.
aimValue *= 1.0f + 0.35f * Math.Min(1.0f, totalHits / 200.0f) +
aimValue *= 1.0 + 0.35 * Math.Min(1.0, totalHits / 200.0) +
(totalHits > 200
? 0.3f * Math.Min(1.0f, (totalHits - 200) / 300.0f) +
(totalHits > 500 ? (totalHits - 500) / 1200.0f : 0.0f)
: 0.0f);
? 0.3 * Math.Min(1.0, (totalHits - 200) / 300.0) +
(totalHits > 500 ? (totalHits - 500) / 1200.0 : 0.0)
: 0.0);
}
// Scale the aim value with accuracy _slightly_
aimValue *= 0.5f + accuracy / 2.0f;
aimValue *= 0.5 + accuracy / 2.0;
// It is important to also consider accuracy difficulty when doing that
aimValue *= 0.98f + Math.Pow(Attributes.OverallDifficulty, 2) / 2500;
aimValue *= 0.98 + Math.Pow(Attributes.OverallDifficulty, 2) / 2500;
return aimValue;
}
private double computeSpeedValue()
{
double speedValue = Math.Pow(5.0f * Math.Max(1.0f, Attributes.SpeedStrain / 0.0675f) - 4.0f, 3.0f) / 100000.0f;
double speedValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.SpeedStrain / 0.0675) - 4.0, 3.0) / 100000.0;
// Longer maps are worth more
speedValue *= 0.95f + 0.4f * Math.Min(1.0f, totalHits / 2000.0f) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0f) * 0.5f : 0.0f);
speedValue *= 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
// Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available
speedValue *= Math.Pow(0.97f, countMiss);
speedValue *= Math.Pow(0.97, countMiss);
// Combo scaling
if (beatmapMaxCombo > 0)
speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f);
speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(beatmapMaxCombo, 0.8), 1.0);
double approachRateFactor = 1.0f;
if (Attributes.ApproachRate > 10.33f)
approachRateFactor += 0.3f * (Attributes.ApproachRate - 10.33f);
double approachRateFactor = 1.0;
if (Attributes.ApproachRate > 10.33)
approachRateFactor += 0.3 * (Attributes.ApproachRate - 10.33);
speedValue *= approachRateFactor;
if (mods.Any(m => m is OsuModHidden))
speedValue *= 1.0f + 0.04f * (12.0f - Attributes.ApproachRate);
speedValue *= 1.0 + 0.04 * (12.0 - Attributes.ApproachRate);
// Scale the speed value with accuracy _slightly_
speedValue *= 0.02f + accuracy;
speedValue *= 0.02 + accuracy;
// It is important to also consider accuracy difficulty when doing that
speedValue *= 0.96f + Math.Pow(Attributes.OverallDifficulty, 2) / 1600;
speedValue *= 0.96 + Math.Pow(Attributes.OverallDifficulty, 2) / 1600;
return speedValue;
}
@ -190,15 +190,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty
// Lots of arbitrary values from testing.
// Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution
double accuracyValue = Math.Pow(1.52163f, Attributes.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f;
double accuracyValue = Math.Pow(1.52163, Attributes.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83;
// Bonus for many hitcircles - it's harder to keep good accuracy up for longer
accuracyValue *= Math.Min(1.15f, Math.Pow(amountHitObjectsWithAccuracy / 1000.0f, 0.3f));
accuracyValue *= Math.Min(1.15, Math.Pow(amountHitObjectsWithAccuracy / 1000.0, 0.3));
if (mods.Any(m => m is OsuModHidden))
accuracyValue *= 1.08f;
accuracyValue *= 1.08;
if (mods.Any(m => m is OsuModFlashlight))
accuracyValue *= 1.02f;
accuracyValue *= 1.02;
return accuracyValue;
}

View File

@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
double strainValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.StarRating / 0.0075) - 4.0, 2.0) / 100000.0;
// Longer maps are worth more
double lengthBonus = 1 + 0.1f * Math.Min(1.0, totalHits / 1500.0);
double lengthBonus = 1 + 0.1 * Math.Min(1.0, totalHits / 1500.0);
strainValue *= lengthBonus;
// Penalize misses exponentially. This mainly fixes tag4 maps and the likes until a per-hitobject solution is available