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:
parent
c8e9602e15
commit
c2e5d767f9
@ -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.
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user