1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-13 00:42:55 +08:00

added density aim multiplier

This commit is contained in:
Givikap120 2024-02-23 19:52:00 +02:00
parent 9e6ae3587a
commit 5d4c78239b
8 changed files with 44 additions and 55 deletions

View File

@ -18,8 +18,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
private const double overlap_multiplier = 0.8; private const double overlap_multiplier = 0.8;
public static double CalculateDenstityOf(OsuDifficultyHitObject currObj) public static double EvaluateDenstityOf(DifficultyHitObject current)
{ {
var currObj = (OsuDifficultyHitObject)current;
double density = 0; double density = 0;
double densityAnglesNerf = -2; // we have threshold of 2, so 2 or same angles won't be punished double densityAnglesNerf = -2; // we have threshold of 2, so 2 or same angles won't be punished
@ -34,8 +35,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
double loopDifficulty = currObj.OpacityAt(loopObj.BaseObject.StartTime, false); double loopDifficulty = currObj.OpacityAt(loopObj.BaseObject.StartTime, false);
// Small distances means objects may be cheesed, so it doesn't matter whether they are arranged confusingly. // Small distances means objects may be cheesed, so it doesn't matter whether they are arranged confusingly.
// For HD: it's not subtracting anything cuz it's multiplied by the aim difficulty anyways. loopDifficulty *= logistic((loopObj.MinimumJumpDistance - 30) / 10);
loopDifficulty *= logistic((loopObj.MinimumJumpDistance - 60) / 10);
// Reduce density bonus for this object if they're too apart in time // Reduce density bonus for this object if they're too apart in time
// Nerf starts on 1500ms and reaches maximum (*=0) on 3000ms // Nerf starts on 1500ms and reaches maximum (*=0) on 3000ms
@ -123,14 +123,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
return screenOverlapDifficulty; return screenOverlapDifficulty;
} }
public static double EvaluateDensityDifficultyOf(DifficultyHitObject current) public static double EvaluateDifficultyOf(DifficultyHitObject current)
{ {
if (current.BaseObject is Spinner || current.Index == 0) if (current.BaseObject is Spinner || current.Index == 0)
return 0; return 0;
var currObj = (OsuDifficultyHitObject)current; var currObj = (OsuDifficultyHitObject)current;
double pastObjectDifficultyInfluence = CalculateDenstityOf(currObj); double pastObjectDifficultyInfluence = EvaluateDenstityOf(current);
double screenOverlapDifficulty = CalculateOverlapDifficultyOf(currObj); double screenOverlapDifficulty = CalculateOverlapDifficultyOf(currObj);
double difficulty = Math.Pow(4 * Math.Log(Math.Max(1, pastObjectDifficultyInfluence)), 2.3); double difficulty = Math.Pow(4 * Math.Log(Math.Max(1, pastObjectDifficultyInfluence)), 2.3);

View File

@ -123,28 +123,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
// https://www.desmos.com/calculator/hbj7swzlth // https://www.desmos.com/calculator/hbj7swzlth
public static double GetDifficulty(double preempt) public static double GetDifficulty(double preempt)
{ {
double value = Math.Pow(3, 3 - 0.01 * preempt); // 1 for 300ms, 0.25 for 400ms, 0.0625 for 500ms double value = Math.Pow(3.5, 3 - 0.01 * preempt); // 1 for 300ms, 0.25 for 400ms, 0.0625 for 500ms
value = softmin(value, 2, 1.7); // use softmin to achieve full-memory cap, 2 times more than AR11 (300ms) value = softmin(value, 2, 1.7); // use softmin to achieve full-memory cap, 2 times more than AR11 (300ms)
return value; return value;
} }
// This is very accurate on preempt > 300ms, breaking starting somewhere around 120ms
public static double GetPreempt(double difficulty)
{
double fixCoef = difficulty / GetDifficulty(highArCurveReversed(difficulty));
return highArCurveReversed(difficulty * fixCoef);
}
// This is an approximation cuz high AR curve is unsolvable
// https://www.desmos.com/calculator/n9vk18bcyh
private static double highArCurveReversed(double value)
{
double helperValue = value / Math.Pow(1 - Math.Pow(1.7, value - 2), 0.45);
double preempt = -(Math.Log(helperValue, 3) - 3) / 0.01;
return preempt;
}
// We are using mutiply and divide instead of add and subtract, so values won't be negative // We are using mutiply and divide instead of add and subtract, so values won't be negative
// https://www.desmos.com/calculator/fv5xerwpd2 // https://www.desmos.com/calculator/fv5xerwpd2
private static double softmin(double a, double b, double power = Math.E) => a * b / Math.Log(Math.Pow(power, a) + Math.Pow(power, b), power); private static double softmin(double a, double b, double power = Math.E) => a * b / Math.Log(Math.Pow(power, a) + Math.Pow(power, b), power);

View File

@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
if (mods.Any(h => h is OsuModFlashlight)) if (mods.Any(h => h is OsuModFlashlight))
baseFlashlightPerformance = Math.Pow(flashlightRating, 2.0) * 25.0; baseFlashlightPerformance = Math.Pow(flashlightRating, 2.0) * 25.0;
double baseReadingLowARPerformance = Math.Pow(readingLowARRating, 2.5) * 17.0; double baseReadingLowARPerformance = ReadingLowAR.DifficultyToPerformance(readingLowARRating);
double baseReadingHighARPerformance = OsuStrainSkill.DifficultyToPerformance(readingHighARRating); double baseReadingHighARPerformance = OsuStrainSkill.DifficultyToPerformance(readingHighARRating);
double baseReadingARPerformance = Math.Pow(Math.Pow(baseReadingLowARPerformance, SUM_POWER) + Math.Pow(baseReadingHighARPerformance, SUM_POWER), 1.0 / SUM_POWER); double baseReadingARPerformance = Math.Pow(Math.Pow(baseReadingLowARPerformance, SUM_POWER) + Math.Pow(baseReadingHighARPerformance, SUM_POWER), 1.0 / SUM_POWER);

View File

@ -261,7 +261,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
if (score.Mods.Any(m => m is OsuModTouchDevice)) if (score.Mods.Any(m => m is OsuModTouchDevice))
rawReading = Math.Pow(rawReading, 0.8); rawReading = Math.Pow(rawReading, 0.8);
double readingValue = Math.Pow(rawReading, 2.5) * 17.0; double readingValue = ReadingLowAR.DifficultyToPerformance(rawReading);
// Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses. // Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0) if (effectiveMissCount > 0)

View File

@ -35,6 +35,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
/// </summary> /// </summary>
protected virtual double DifficultyMultiplier => DEFAULT_DIFFICULTY_MULTIPLIER; protected virtual double DifficultyMultiplier => DEFAULT_DIFFICULTY_MULTIPLIER;
protected virtual double StrainDecayBase => 0.15;
protected double StrainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000);
protected OsuStrainSkill(Mod[] mods) protected OsuStrainSkill(Mod[] mods)
: base(mods) : base(mods)
{ {

View File

@ -16,18 +16,31 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
public class ReadingLowAR : GraphSkill public class ReadingLowAR : GraphSkill
{ {
private readonly List<double> difficulties = new List<double>(); private readonly List<double> difficulties = new List<double>();
private double skillMultiplier => 2; private double skillMultiplier => 1.3;
private double aimComponentMultiplier => 0.7;
//private double skillMultiplier => 2;
public ReadingLowAR(Mod[] mods) public ReadingLowAR(Mod[] mods)
: base(mods) : base(mods)
{ {
} }
private double strainDecayBase => 0.15;
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000);
private double currentDensityAimStrain = 0;
public override void Process(DifficultyHitObject current) public override void Process(DifficultyHitObject current)
{ {
double currentDifficulty = ReadingEvaluator.EvaluateDensityDifficultyOf(current) * skillMultiplier; double densityFactor = Math.Max(0, Math.Pow(ReadingEvaluator.EvaluateDenstityOf(current), 1.5) - 1);
// double density = Math.Max(0, ReadingEvaluator.EvaluateDenstityOf(current));
currentDensityAimStrain *= strainDecay(current.DeltaTime);
currentDensityAimStrain += densityFactor * AimEvaluator.EvaluateDifficultyOf(current, false) * aimComponentMultiplier;
difficulties.Add(currentDifficulty); double densityReadingDifficulty = ReadingEvaluator.EvaluateDifficultyOf(current);
double totalDensityDifficulty = (currentDensityAimStrain + densityReadingDifficulty) * skillMultiplier;
difficulties.Add(totalDensityDifficulty);
if (current.Index == 0) if (current.Index == 0)
CurrentSectionEnd = Math.Ceiling(current.StartTime / SectionLength) * SectionLength; CurrentSectionEnd = Math.Ceiling(current.StartTime / SectionLength) * SectionLength;
@ -39,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
CurrentSectionEnd += SectionLength; CurrentSectionEnd += SectionLength;
} }
CurrentSectionPeak = Math.Max(currentDifficulty, CurrentSectionPeak); CurrentSectionPeak = Math.Max(totalDensityDifficulty, CurrentSectionPeak);
} }
private double reducedNoteCount => 5; private double reducedNoteCount => 5;
@ -71,6 +84,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return difficulty; return difficulty;
} }
public static double DifficultyToPerformance(double difficulty) => Math.Pow(difficulty, 3) * 10.0;
} }
public class ReadingHidden : OsuStrainSkill public class ReadingHidden : OsuStrainSkill
@ -82,15 +97,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
private double currentStrain; private double currentStrain;
private double skillMultiplier => 5; private double skillMultiplier => 5;
private double strainDecayBase => 0.15;
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000); protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => currentStrain * StrainDecay(time - current.Previous(0).StartTime);
protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => currentStrain * strainDecay(time - current.Previous(0).StartTime);
protected override double StrainValueAt(DifficultyHitObject current) protected override double StrainValueAt(DifficultyHitObject current)
{ {
currentStrain *= strainDecay(current.DeltaTime); currentStrain *= StrainDecay(current.DeltaTime);
// We're not using slider aim because we assuming that HD doesn't makes sliders harder (what is not true, but we will ignore this for now) // We're not using slider aim because we assuming that HD doesn't makes sliders harder (what is not true, but we will ignore this for now)
double hiddenDifficulty = AimEvaluator.EvaluateDifficultyOf(current, false); double hiddenDifficulty = AimEvaluator.EvaluateDifficultyOf(current, false);

View File

@ -29,12 +29,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
private readonly List<double> difficulties = new List<double>(); private readonly List<double> difficulties = new List<double>();
private int objectsCount = 0; private int objectsCount = 0;
private double preempt = -1;
public override void Process(DifficultyHitObject current) public override void Process(DifficultyHitObject current)
{ {
if (preempt < 0) preempt = ((OsuDifficultyHitObject)current).Preempt;
aimComponent.Process(current); aimComponent.Process(current);
speedComponent.Process(current); speedComponent.Process(current);
@ -97,17 +94,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
private bool adjustHighAR; private bool adjustHighAR;
private double currentStrain; private double currentStrain;
private double skillMultiplier => 17.8; private double skillMultiplier => 17;
private double defaultValueMultiplier => 30; private double defaultValueMultiplier => 50;
private double strainDecayBase => 0.15;
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000); protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => currentStrain * StrainDecay(time - current.Previous(0).StartTime);
protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => currentStrain * strainDecay(time - current.Previous(0).StartTime);
protected override double StrainValueAt(DifficultyHitObject current) protected override double StrainValueAt(DifficultyHitObject current)
{ {
currentStrain *= strainDecay(current.DeltaTime); currentStrain *= StrainDecay(current.DeltaTime);
double aimDifficulty = AimEvaluator.EvaluateDifficultyOf(current, true); double aimDifficulty = AimEvaluator.EvaluateDifficultyOf(current, true);
double readingDifficulty = ReadingHighAREvaluator.EvaluateDifficultyOf(current, adjustHighAR); double readingDifficulty = ReadingHighAREvaluator.EvaluateDifficultyOf(current, adjustHighAR);
@ -122,8 +116,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
public class HighARSpeedComponent : OsuStrainSkill public class HighARSpeedComponent : OsuStrainSkill
{ {
private double skillMultiplier => 850; private double skillMultiplier => 820;
private double strainDecayBase => 0.3; protected override double StrainDecayBase => 0.3;
private double currentStrain; private double currentStrain;
private double currentRhythm; private double currentRhythm;
@ -133,15 +127,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{ {
} }
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000); protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => (currentStrain * currentRhythm) * StrainDecay(time - current.Previous(0).StartTime);
protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => (currentStrain * currentRhythm) * strainDecay(time - current.Previous(0).StartTime);
protected override double StrainValueAt(DifficultyHitObject current) protected override double StrainValueAt(DifficultyHitObject current)
{ {
OsuDifficultyHitObject currODHO = (OsuDifficultyHitObject)current; OsuDifficultyHitObject currODHO = (OsuDifficultyHitObject)current;
currentStrain *= strainDecay(currODHO.StrainTime); currentStrain *= StrainDecay(currODHO.StrainTime);
double speedDifficulty = SpeedEvaluator.EvaluateDifficultyOf(current) * skillMultiplier; double speedDifficulty = SpeedEvaluator.EvaluateDifficultyOf(current) * skillMultiplier;
speedDifficulty *= Math.Pow(ReadingHighAREvaluator.EvaluateDifficultyOf(current, false), 2); speedDifficulty *= Math.Pow(ReadingHighAREvaluator.EvaluateDifficultyOf(current, false), 2);

View File

@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
public class Speed : OsuStrainSkill public class Speed : OsuStrainSkill
{ {
private double skillMultiplier => 1375; private double skillMultiplier => 1375;
private double strainDecayBase => 0.3; protected override double StrainDecayBase => 0.3;
private double currentStrain; private double currentStrain;
private double currentRhythm; private double currentRhythm;
@ -32,15 +32,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{ {
} }
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000); protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => (currentStrain * currentRhythm) * StrainDecay(time - current.Previous(0).StartTime);
protected override double CalculateInitialStrain(double time, DifficultyHitObject current) => (currentStrain * currentRhythm) * strainDecay(time - current.Previous(0).StartTime);
protected override double StrainValueAt(DifficultyHitObject current) protected override double StrainValueAt(DifficultyHitObject current)
{ {
OsuDifficultyHitObject currODHO = (OsuDifficultyHitObject)current; OsuDifficultyHitObject currODHO = (OsuDifficultyHitObject)current;
currentStrain *= strainDecay(currODHO.StrainTime); currentStrain *= StrainDecay(currODHO.StrainTime);
currentStrain += SpeedEvaluator.EvaluateDifficultyOf(current) * skillMultiplier; currentStrain += SpeedEvaluator.EvaluateDifficultyOf(current) * skillMultiplier;
currentRhythm = currODHO.RhythmDifficulty; currentRhythm = currODHO.RhythmDifficulty;