mirror of
https://github.com/ppy/osu
synced 2024-12-14 19:06:07 +00:00
removed ppCalc changes and sliderabuseChecks
This commit is contained in:
parent
750c5a0181
commit
cb605f9156
@ -25,8 +25,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
private int countMeh;
|
||||
private int countMiss;
|
||||
|
||||
private int effectiveMissCount;
|
||||
|
||||
public OsuPerformanceCalculator(Ruleset ruleset, DifficultyAttributes attributes, ScoreInfo score)
|
||||
: base(ruleset, attributes, score)
|
||||
{
|
||||
@ -41,23 +39,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
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.
|
||||
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 *= Math.Max(0.90, 1.0 - 0.02 * effectiveMissCount);
|
||||
multiplier *= Math.Max(0.90, 1.0 - 0.02 * countMiss);
|
||||
|
||||
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))
|
||||
{
|
||||
effectiveMissCount += countOk + countMeh;
|
||||
multiplier *= 0.6;
|
||||
}
|
||||
|
||||
double aimValue = computeAimValue();
|
||||
double speedValue = computeSpeedValue();
|
||||
double accuracyValue = computeAccuracyValue();
|
||||
@ -100,8 +91,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
aimValue *= lengthBonus;
|
||||
|
||||
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
||||
if (effectiveMissCount > 0)
|
||||
aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), effectiveMissCount);
|
||||
if (countMiss > 0)
|
||||
aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), countMiss);
|
||||
|
||||
// Combo scaling.
|
||||
if (Attributes.MaxCombo > 0)
|
||||
@ -117,18 +108,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
|
||||
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 * 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.
|
||||
// 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.0 + 0.04 * (12.0 - Attributes.ApproachRate);
|
||||
}
|
||||
|
||||
aimValue *= approachRateBonus;
|
||||
|
||||
// Scale the aim value with accuracy
|
||||
aimValue *= accuracy;
|
||||
// Scale the aim value with accuracy _slightly_.
|
||||
aimValue *= 0.5 + accuracy / 2.0;
|
||||
// It is important to also consider accuracy difficulty when doing that.
|
||||
aimValue *= 0.98 + Math.Pow(Attributes.OverallDifficulty, 2) / 2500;
|
||||
|
||||
@ -145,8 +132,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
speedValue *= lengthBonus;
|
||||
|
||||
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
||||
if (effectiveMissCount > 0)
|
||||
speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
|
||||
if (countMiss > 0)
|
||||
speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), Math.Pow(countMiss, .875));
|
||||
|
||||
// Combo scaling.
|
||||
if (Attributes.MaxCombo > 0)
|
||||
@ -160,20 +147,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
|
||||
speedValue *= 1.0 + (0.03 + 0.37 * approachRateTotalHitsFactor) * approachRateFactor;
|
||||
|
||||
if (mods.Any(m => m is OsuModBlinds))
|
||||
{
|
||||
// Increasing the speed value by object count for Blinds isn't ideal, so the minimum buff is given.
|
||||
speedValue *= 1.12;
|
||||
}
|
||||
else if (mods.Any(m => m 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.
|
||||
if (mods.Any(m => m is OsuModHidden))
|
||||
speedValue *= 1.0 + 0.04 * (12.0 - Attributes.ApproachRate);
|
||||
}
|
||||
|
||||
// Scale the speed value with accuracy and OD.
|
||||
speedValue *= (0.95 + Math.Pow(Attributes.OverallDifficulty, 2) / 750) * Math.Pow(accuracy, (14.5 - Math.Max(Attributes.OverallDifficulty, 8)) / 2);
|
||||
|
||||
// Scale the speed value with # of 50s to punish doubletapping.
|
||||
speedValue *= Math.Pow(0.98, countMeh < totalHits / 500.0 ? 0 : countMeh - totalHits / 500.0);
|
||||
|
||||
@ -182,9 +160,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
|
||||
private double computeAccuracyValue()
|
||||
{
|
||||
if (mods.Any(h => h is OsuModRelax))
|
||||
return 0.0;
|
||||
|
||||
// This percentage only considers HitCircles of any value - in this part of the calculation we focus on hitting the timing hit window.
|
||||
double betterAccuracyPercentage;
|
||||
int amountHitObjectsWithAccuracy = Attributes.HitCircleCount;
|
||||
@ -205,12 +180,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
// Bonus for many hitcircles - it's harder to keep good accuracy up for longer.
|
||||
accuracyValue *= Math.Min(1.15, Math.Pow(amountHitObjectsWithAccuracy / 1000.0, 0.3));
|
||||
|
||||
// Increasing the accuracy value by object count for Blinds isn't ideal, so the minimum buff is given.
|
||||
if (mods.Any(m => m is OsuModBlinds))
|
||||
accuracyValue *= 1.14;
|
||||
else if (mods.Any(m => m is OsuModHidden))
|
||||
if (mods.Any(m => m is OsuModHidden))
|
||||
accuracyValue *= 1.08;
|
||||
|
||||
if (mods.Any(m => m is OsuModFlashlight))
|
||||
accuracyValue *= 1.02;
|
||||
|
||||
@ -234,8 +205,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
flashlightValue *= 1.3;
|
||||
|
||||
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
|
||||
if (effectiveMissCount > 0)
|
||||
flashlightValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
|
||||
if (countMiss > 0)
|
||||
flashlightValue *= 0.97 * Math.Pow(1 - Math.Pow((double)countMiss / totalHits, 0.775), Math.Pow(countMiss, .875));
|
||||
|
||||
// Combo scaling.
|
||||
if (Attributes.MaxCombo > 0)
|
||||
@ -253,24 +224,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
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;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
public class OsuDifficultyHitObject : DifficultyHitObject
|
||||
{
|
||||
private const int normalized_radius = 50; // Change radius to 50 to make 100 the diameter. Easier for mental maths.
|
||||
private const int min_delta_time = 25;
|
||||
|
||||
protected new OsuHitObject BaseObject => (OsuHitObject)base.BaseObject;
|
||||
|
||||
@ -26,7 +27,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
/// </summary>
|
||||
public double MovementDistance { get; private set; }
|
||||
|
||||
/// <summary>JumpTravel
|
||||
/// <summary>
|
||||
/// Normalized distance between the start and end position of the previous <see cref="OsuDifficultyHitObject"/>.
|
||||
/// </summary>
|
||||
public double TravelDistance { get; private set; }
|
||||
@ -62,7 +63,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
this.lastObject = (OsuHitObject)lastObject;
|
||||
|
||||
// Capped to 25ms to prevent difficulty calculation breaking from simulatenous objects.
|
||||
StrainTime = Math.Max(DeltaTime, 25);
|
||||
StrainTime = Math.Max(DeltaTime, min_delta_time);
|
||||
|
||||
setDistances(clockRate);
|
||||
}
|
||||
@ -82,22 +83,19 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
scalingFactor *= 1 + smallCircleBonus;
|
||||
}
|
||||
|
||||
double sliderAbuseIndex = 1;
|
||||
|
||||
if (lastObject is Slider lastSlider)
|
||||
{
|
||||
computeSliderCursorPosition(lastSlider);
|
||||
sliderAbuseIndex = Math.Clamp(Vector2.Subtract(lastSlider.StackedPosition * scalingFactor, BaseObject.StackedPosition * scalingFactor).Length - 100, 0, 25) / 25;
|
||||
TravelDistance = lastSlider.LazyTravelDistance * scalingFactor * sliderAbuseIndex;
|
||||
TravelTime = Math.Max(lastSlider.LazyTravelTime / clockRate, 25);
|
||||
MovementTime = Math.Max(StrainTime - TravelTime, 25);
|
||||
TravelDistance = lastSlider.LazyTravelDistance * scalingFactor;
|
||||
TravelTime = Math.Max(lastSlider.LazyTravelTime / clockRate, min_delta_time);
|
||||
MovementTime = Math.Max(StrainTime - TravelTime, min_delta_time);
|
||||
MovementDistance = Vector2.Subtract(lastSlider.TailCircle.StackedPosition, BaseObject.StackedPosition).Length * scalingFactor;
|
||||
}
|
||||
|
||||
Vector2 lastCursorPosition = getEndCursorPosition(lastObject);
|
||||
|
||||
JumpDistance = (BaseObject.StackedPosition * scalingFactor - lastCursorPosition * scalingFactor).Length * sliderAbuseIndex;
|
||||
MovementDistance = Math.Min(JumpDistance, MovementDistance) * sliderAbuseIndex;
|
||||
JumpDistance = (BaseObject.StackedPosition * scalingFactor - lastCursorPosition * scalingFactor).Length;
|
||||
MovementDistance = Math.Min(JumpDistance, MovementDistance);
|
||||
|
||||
if (lastLastObject != null && !(lastLastObject is Spinner))
|
||||
{
|
||||
@ -120,7 +118,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
|
||||
slider.LazyEndPosition = slider.StackedPosition;
|
||||
|
||||
float approxFollowCircleRadius = (float)(slider.Radius * 2.4);
|
||||
float followCircleRadius = (float)(slider.Radius * 2.4);
|
||||
var computeVertex = new Action<double>(t =>
|
||||
{
|
||||
double progress = (t - slider.StartTime) / slider.SpanDuration;
|
||||
@ -135,11 +133,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
|
||||
|
||||
slider.LazyTravelTime = t - slider.StartTime;
|
||||
|
||||
if (dist > approxFollowCircleRadius)
|
||||
if (dist > followCircleRadius)
|
||||
{
|
||||
// The cursor would be outside the follow circle, we need to move it
|
||||
diff.Normalize(); // Obtain direction of diff
|
||||
dist -= approxFollowCircleRadius;
|
||||
dist -= followCircleRadius;
|
||||
slider.LazyEndPosition += diff * dist;
|
||||
slider.LazyTravelDistance += dist;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
var osuPrevObj = (OsuDifficultyHitObject)Previous[0];
|
||||
var osuLastObj = (OsuDifficultyHitObject)Previous[1];
|
||||
|
||||
double currVelocity = osuCurrObj.JumpDistance / osuCurrObj.StrainTime; // Start iwth the base distance / time
|
||||
double currVelocity = osuCurrObj.JumpDistance / osuCurrObj.StrainTime; // Start with the base distance / time
|
||||
|
||||
if (osuPrevObj.BaseObject is Slider) // If object is a slider
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user