1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-14 05:07:26 +08:00

Angle penalty change

This commit is contained in:
Givikap120 2024-04-14 21:11:59 +03:00
parent 33d1e2fe36
commit 8d080ccd10
3 changed files with 31 additions and 50 deletions

View File

@ -23,12 +23,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
var currObj = (OsuDifficultyHitObject)current;
double density = 0;
double densityAnglesNerf = -2.5; // we have threshold of 2.5
double densityAnglesNerf = -2; // we have threshold of 2
OsuDifficultyHitObject? prevObj0 = null;
double prevAngleNerf = 1;
var readingObjects = currObj.ReadingObjects;
for (int i = 0; i < readingObjects.Count; i++)
{
@ -71,28 +69,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
double currAngleNerf = (loopObj.AnglePredictability / 2) + 0.5;
// Apply the nerf only when it's repeated
double angleNerf = Math.Min(currAngleNerf, prevAngleNerf);
double angleNerf = currAngleNerf;
// Reduce angles nerf if objects are too apart in time
// Angle nerf is starting being reduced from 200ms (150BPM jump) and it reduced to 0 on 2000ms
//double longIntervalFactor = Math.Clamp(1 - (loopObj.StrainTime - 200) / (2000 - 200), 0, 1);
// Bandaid to fix Rubik's Cube +EZ
double wideness = 0;
if (loopObj.Angle.IsNotNull() && loopObj.Angle.Value > Math.PI * 0.5)
{
// Goes from 0 to 1 as angle increasing from 90 degrees to 180
wideness = (loopObj.Angle.Value / Math.PI - 0.5) * 2;
// Transform into cubic scaling
wideness = 1 - Math.Pow(1 - wideness, 3);
}
// But only for sharp angles
angleNerf += wideness * (currAngleNerf - angleNerf);
densityAnglesNerf += Math.Min(angleNerf, loopDifficulty);
prevAngleNerf = currAngleNerf;
densityAnglesNerf += angleNerf * loopDifficulty;
prevObj0 = loopObj;
}
@ -219,7 +198,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
if (osuCurrObj.Angle != null && osuLastObj.Angle != null && currVelocity > 0 && prevVelocity > 0)
{
angleChangeBonus = Math.Pow(Math.Sin((double)((osuCurrObj.Angle - osuLastObj.Angle) / 2)), 2); // Also stealed from xexxar
angleChangeBonus = 1 - osuCurrObj.AnglePredictability;
angleChangeBonus *= Math.Min(currVelocity, prevVelocity) / Math.Max(currVelocity, prevVelocity); // Prevent cheesing
}

View File

@ -163,7 +163,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
setDistances(clockRate);
AnglePredictability = calculateAnglePredictability();
AnglePredictability = CalculateAnglePredictability();
OverlapValues = new Dictionary<OsuDifficultyHitObject, double>();
ReadingObjects = getReadingObjects();
@ -355,7 +355,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
}
}
private double calculateAnglePredictability()
public double CalculateAnglePredictability()
{
OsuDifficultyHitObject? prevObj0 = (OsuDifficultyHitObject?)Previous(0);
OsuDifficultyHitObject? prevObj1 = (OsuDifficultyHitObject?)Previous(1);
@ -372,33 +372,41 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
if (LazyJumpDistance < NORMALISED_RADIUS)
angleDifference *= Math.Pow(LazyJumpDistance / NORMALISED_RADIUS, 2);
// assume worst-case if no angles
double angleDifference1 = 0;
double angleDifference2 = 0;
// Now research previous angles
double angleDifferencePrev = 0;
// How close the smallest angle of curr and prev is to 0
double zeroAngleFactor = 1.0;
// Nerf alternating angles case
if (prevObj1.IsNotNull() && prevObj2.IsNotNull() && prevObj1.Angle.IsNotNull() && prevObj2.Angle.IsNotNull())
if (prevObj1.IsNotNull() && prevObj2.IsNotNull() && prevObj1.Angle.IsNotNull())
{
// Normalized difference
angleDifference1 = Math.Abs(prevObj1.Angle.Value - Angle.Value) / Math.PI;
angleDifference2 = Math.Abs(prevObj2.Angle.Value - prevObj0.Angle.Value) / Math.PI;
angleDifferencePrev = Math.Abs(prevObj1.Angle.Value - Angle.Value);
zeroAngleFactor = Math.Pow(1 - Math.Min(Angle.Value, prevObj0.Angle.Value) / Math.PI, 10);
}
// Will be close to 1 if angleDifference1 and angleDifference2 was both close to 0
double alternatingFactor = Math.Pow((1 - angleDifference1) * (1 - angleDifference2), 2);
// Will be close to 1 if angleDifferencePrev is close to 0
double rescaleFactor = Math.Pow(1 - angleDifferencePrev / Math.PI, 5);
// Be sure to nerf only same rhythms
double rhythmFactor = 1 - getTimeDifference(StrainTime, prevObj0.StrainTime); // 0 on different rhythm, 1 on same rhythm
// 0 on different rhythm, 1 on same rhythm
double rhythmFactor = 1 - getTimeDifference(StrainTime, prevObj0.StrainTime);
if (prevObj1.IsNotNull())
rhythmFactor *= 1 - getTimeDifference(prevObj0.StrainTime, prevObj1.StrainTime);
if (prevObj1.IsNotNull() && prevObj2.IsNotNull())
rhythmFactor *= 1 - getTimeDifference(prevObj1.StrainTime, prevObj2.StrainTime);
double prevAngleAdjust = Math.Max(angleDifference - angleDifference1, 0);
// Get the base - how much alternating difference is lower than current difference
double prevAngleAdjust = Math.Max(angleDifference - angleDifferencePrev, 0);
prevAngleAdjust *= alternatingFactor; // Nerf if alternating
prevAngleAdjust *= rhythmFactor; // Nerf if same rhythms
// Don't apply the nerf when angleDifferencePrev is too high
prevAngleAdjust *= rescaleFactor;
// Don't apply the nerf if rhythm is changing
prevAngleAdjust *= rhythmFactor;
// Don't apply the nerf if neither of previous angles isn't close to 0
prevAngleAdjust *= zeroAngleFactor;
angleDifference -= prevAngleAdjust;
@ -416,15 +424,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Preprocessing
// Angle difference will be considered as 2 times lower if angle is wide
angleDifference /= 1 + wideness;
// Current angle nerf. Angle difference more than 15 degrees gets no penalty
// Angle difference more than 15 degrees gets no penalty
double adjustedAngleDifference = Math.Min(Math.PI / 12, angleDifference);
// WARNING - this thing always gives at least 0.5 angle nerf, this is a bug, but removing it completely ruins everything
// Theoretically - this issue is fixable by changing multipliers everywhere,
// but this is not needed because this bug have no drawbacks outside of algorithm not working as intended
double currAngleNerf = Math.Cos(Math.Min(Math.PI / 2, 4 * adjustedAngleDifference));
return (currAngleNerf - 0.5) * 2;
return rhythmFactor * Math.Cos(Math.Min(Math.PI / 2, 6 * adjustedAngleDifference));
}
public double OpacityAt(double time, bool hidden)

View File

@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
public class ReadingLowAR : GraphSkill
{
private readonly List<double> difficulties = new List<double>();
private double skillMultiplier => 1.25;
private double skillMultiplier => 1.23;
private double aimComponentMultiplier => 0.4;
public ReadingLowAR(Mod[] mods)