1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-15 00:53:10 +08:00

Fixed reading cap

Now it's bound to HDFL difficulty instead of FL
This means that adding HD to a AR12 map will not increase pp from nothing
This commit is contained in:
Givikap120 2024-03-07 18:32:54 +02:00
parent c8e9602e15
commit c2e5d767f9
7 changed files with 47 additions and 16 deletions

View File

@ -62,6 +62,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty
[JsonProperty("flashlight_difficulty")]
public double FlashlightDifficulty { get; set; }
/// <summary>
/// The difficulty corresponding to the flashlight skill with HD (used in capping cognition performance).
/// </summary>
[JsonProperty("hidden_flashlight_difficulty")]
public double HiddenFlashlightDifficulty { get; set; }
/// <summary>
/// Describes how much of <see cref="AimDifficulty"/> is contributed to by hitcircles or sliders.
/// A value closer to 1.0 indicates most of <see cref="AimDifficulty"/> is contributed by hitcircles.

View File

@ -47,6 +47,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double readingHighARRating = Math.Sqrt(skills[5].DifficultyValue()) * DIFFICULTY_MULTIPLIER;
double readingSlidersRating = 0;
double hiddenRating = Math.Sqrt(skills[6].DifficultyValue()) * DIFFICULTY_MULTIPLIER;
double hiddenFlashlightRating = Math.Sqrt(skills[7].DifficultyValue()) * DIFFICULTY_MULTIPLIER;
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
@ -69,7 +70,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
// Cognition
double baseFlashlightPerformance = 0.0;
if (mods.Any(h => h is OsuModFlashlight))
baseFlashlightPerformance = Math.Pow(flashlightRating, 2.0) * 25.0;
baseFlashlightPerformance = Flashlight.DifficultyToPerformance(flashlightRating);
double baseReadingLowARPerformance = ReadingLowAR.DifficultyToPerformance(readingLowARRating);
double baseReadingHighARPerformance = OsuStrainSkill.DifficultyToPerformance(readingHighARRating);
@ -79,7 +80,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double baseReadingHiddenPerformance = 0;
if (mods.Any(h => h is OsuModHidden))
baseReadingHiddenPerformance = Math.Pow(hiddenRating, 2.0) * 25.0;
baseReadingHiddenPerformance = ReadingHidden.DifficultyToPerformance(hiddenRating);
double baseReadingSliderPerformance = 0;
double baseReadingNonARPerformance = baseReadingHiddenPerformance + baseReadingSliderPerformance;
@ -96,8 +97,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty
// Limit cognition by full memorisation difficulty
double cognitionPerformance = Math.Pow(Math.Pow(baseFlashlightARPerformance, SUM_POWER) + Math.Pow(baseReadingNonARPerformance, SUM_POWER), 1.0 / SUM_POWER);
double mechanicalPerformance = Math.Pow(Math.Pow(baseAimPerformance, SUM_POWER) + Math.Pow(baseSpeedPerformance, SUM_POWER), 1.0 / SUM_POWER);
double potentialFlashlightPerformance = OsuPerformanceCalculator.ComputePerfectFlashlightValue(flashlightRating, hitCirclesCount + sliderCount);
cognitionPerformance = OsuPerformanceCalculator.AdjustCognitionPerformance(cognitionPerformance, mechanicalPerformance, potentialFlashlightPerformance);
double maxHiddenFlashlightPerformance = OsuPerformanceCalculator.ComputePerfectFlashlightValue(hiddenFlashlightRating, hitCirclesCount + sliderCount);
cognitionPerformance = OsuPerformanceCalculator.AdjustCognitionPerformance(cognitionPerformance, mechanicalPerformance, maxHiddenFlashlightPerformance);
double basePerformance =
Math.Pow(
@ -115,8 +118,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double hitWindowGreat = hitWindows.WindowFor(HitResult.Great) / clockRate;
//var test = ((ReadingHighAR)skills[5]).GetAimSpeed();
OsuDifficultyAttributes attributes = new OsuDifficultyAttributes
{
StarRating = starRating,
@ -129,6 +130,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
ReadingDifficultySliders = readingSlidersRating,
HiddenDifficulty = hiddenRating,
FlashlightDifficulty = flashlightRating,
HiddenFlashlightDifficulty = hiddenFlashlightRating,
SliderFactor = sliderFactor,
ApproachRate = IBeatmapDifficultyInfo.InverseDifficultyRange(preempt, 1800, 1200, 450),
OverallDifficulty = (80 - hitWindowGreat) / 6,
@ -168,6 +170,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
new ReadingLowAR(mods),
new ReadingHighAR(mods),
new ReadingHidden(mods),
new HiddenFlashlight(mods),
};
if (mods.Any(h => h is OsuModFlashlight))

View File

@ -69,8 +69,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty
// Cognition
// Preferably this value should be used for capping low AR reading performance
// Because it should have lower cap (you can actually see)
// But it will make formula really weird and overcomplicated
double potentialFlashlightValue = computeFlashlightValue(score, osuAttributes);
// Get HDFL value for capping reading performance
double potentialHiddenFlashlightValue = computeFlashlightValue(score, osuAttributes, true);
double flashlightValue = potentialFlashlightValue;
if (!score.Mods.Any(h => h is OsuModFlashlight))
flashlightValue = 0.0;
@ -91,7 +97,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double readingNonARValue = readingHDValue + readingSlidersValue;
double cognitionValue = Math.Pow(Math.Pow(flashlightARValue, power) + Math.Pow(readingNonARValue, power), 1.0 / power);
cognitionValue = AdjustCognitionPerformance(cognitionValue, mechanicalValue, potentialFlashlightValue);
cognitionValue = AdjustCognitionPerformance(cognitionValue, mechanicalValue, potentialHiddenFlashlightValue);
double accuracyValue = computeAccuracyValue(score, osuAttributes);
@ -222,9 +228,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty
return accuracyValue;
}
private double computeFlashlightValue(ScoreInfo score, OsuDifficultyAttributes attributes)
private double computeFlashlightValue(ScoreInfo score, OsuDifficultyAttributes attributes, bool alwaysUseHD = false)
{
double flashlightValue = Math.Pow(attributes.FlashlightDifficulty, 2.0) * 25.0;
double flashlightValue = Math.Pow(alwaysUseHD ? attributes.HiddenFlashlightDifficulty : attributes.FlashlightDifficulty, 2.0) * 25.0;
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
@ -246,7 +252,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
public static double ComputePerfectFlashlightValue(double flashlightDifficulty, int objectsCount)
{
double flashlightValue = Math.Pow(flashlightDifficulty, 2.0) * 25.0;
double flashlightValue = Flashlight.DifficultyToPerformance(flashlightDifficulty);
flashlightValue *= 0.7 + 0.1 * Math.Min(1.0, objectsCount / 200.0) +
(objectsCount > 200 ? 0.2 * Math.Min(1.0, (objectsCount - 200) / 200.0) : 0.0);
@ -341,8 +347,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
return 0.0;
double rawReading = attributes.HiddenDifficulty;
//double readingValue = Math.Pow(rawReading, 2.0) * 25.0;
double readingValue = Math.Pow(rawReading, 2.0) * 25.0;
double readingValue = ReadingHidden.DifficultyToPerformance(attributes.HiddenDifficulty);
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
@ -386,7 +391,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
// Avoid it being broken on millions of pp, ruins it being continious, but it will never happen on normal circumstances
if (capPerformance > 10000 || cognitionPerformance > 10000) cognitionPerformance = Math.Min(capPerformance, cognitionPerformance);
else cognitionPerformance = 100 * softmin(capPerformance / 100, cognitionPerformance / 100, 100);
else cognitionPerformance = 1000 * softmin(capPerformance / 1000, cognitionPerformance / 1000, 100);
return cognitionPerformance;
}

View File

@ -263,12 +263,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
}
double fadeInStartTime = BaseObject.StartTime - BaseObject.TimePreempt;
double fadeInDuration = BaseObject.TimeFadeIn;
double fadeInDuration = BaseObject.TimeFadeInRaw;
if (hidden)
{
// Taken from OsuModHidden.
double fadeOutStartTime = BaseObject.StartTime - BaseObject.TimePreempt + BaseObject.TimeFadeIn;
double fadeOutStartTime = BaseObject.StartTime - BaseObject.TimePreempt + BaseObject.TimeFadeInRaw;
double fadeOutDuration = BaseObject.TimePreempt * OsuModHidden.FADE_OUT_DURATION_MULTIPLIER;
return Math.Min

View File

@ -17,6 +17,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
public class Flashlight : StrainSkill
{
private readonly bool hasHiddenMod;
protected virtual bool HasHiddenMod => hasHiddenMod;
public Flashlight(Mod[] mods)
: base(mods)
@ -36,11 +37,23 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
protected override double StrainValueAt(DifficultyHitObject current)
{
currentStrain *= strainDecay(current.DeltaTime);
currentStrain += FlashlightEvaluator.EvaluateDifficultyOf(current, hasHiddenMod) * skillMultiplier;
currentStrain += FlashlightEvaluator.EvaluateDifficultyOf(current, HasHiddenMod) * skillMultiplier;
return currentStrain;
}
public override double DifficultyValue() => GetCurrentStrainPeaks().Sum() * OsuStrainSkill.DEFAULT_DIFFICULTY_MULTIPLIER;
public static double DifficultyToPerformance(double difficulty) => Math.Pow(difficulty, 2) * 25.0;
}
public class HiddenFlashlight : Flashlight
{
protected override bool HasHiddenMod => true;
public HiddenFlashlight(Mod[] mods)
: base(mods)
{
}
}
}

View File

@ -113,5 +113,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return currentStrain;
}
public static double DifficultyToPerformance(double difficulty) => Math.Pow(difficulty, 2) * 25.0;
}
}

View File

@ -49,6 +49,7 @@ namespace osu.Game.Rulesets.Osu.Objects
public double TimePreempt = 600;
public double TimeFadeIn = 400;
public double TimeFadeInRaw = 400;
private HitObjectProperty<Vector2> position;
@ -165,6 +166,7 @@ namespace osu.Game.Rulesets.Osu.Objects
// Note that this doesn't exactly match the AR>10 visuals as they're classically known, but it feels good.
// This adjustment is necessary for AR>10, otherwise TimePreempt can become smaller leading to hitcircles not fully fading in.
TimeFadeIn = 400 * Math.Min(1, TimePreempt / PREEMPT_MIN);
TimeFadeInRaw = TimeFadeIn;
Scale = LegacyRulesetExtensions.CalculateScaleFromCircleSize(difficulty.CircleSize, true);
}