mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:07:52 +08:00
Merge pull request #15035 from emu1337/speed-acc-scaling
Change speed accuracy scaling to be closer to worst case scenario
This commit is contained in:
commit
d4aa18112b
@ -25,6 +25,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
[JsonProperty("speed_difficulty")]
|
||||
public double SpeedDifficulty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of clickable objects weighted by difficulty.
|
||||
/// Related to <see cref="SpeedDifficulty"/>
|
||||
/// </summary>
|
||||
[JsonProperty("speed_note_count")]
|
||||
public double SpeedNoteCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The difficulty corresponding to the flashlight skill.
|
||||
/// </summary>
|
||||
@ -93,6 +100,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
yield return (ATTRIB_ID_FLASHLIGHT, FlashlightDifficulty);
|
||||
|
||||
yield return (ATTRIB_ID_SLIDER_FACTOR, SliderFactor);
|
||||
yield return (ATTRIB_ID_SPEED_NOTE_COUNT, SpeedNoteCount);
|
||||
}
|
||||
|
||||
public override void FromDatabaseAttributes(IReadOnlyDictionary<int, double> values, IBeatmapOnlineInfo onlineInfo)
|
||||
@ -107,6 +115,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
StarRating = values[ATTRIB_ID_DIFFICULTY];
|
||||
FlashlightDifficulty = values.GetValueOrDefault(ATTRIB_ID_FLASHLIGHT);
|
||||
SliderFactor = values[ATTRIB_ID_SLIDER_FACTOR];
|
||||
SpeedNoteCount = values[ATTRIB_ID_SPEED_NOTE_COUNT];
|
||||
|
||||
DrainRate = onlineInfo.DrainRate;
|
||||
HitCircleCount = onlineInfo.CircleCount;
|
||||
|
@ -38,6 +38,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
double aimRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier;
|
||||
double aimRatingNoSliders = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
|
||||
double speedRating = Math.Sqrt(skills[2].DifficultyValue()) * difficulty_multiplier;
|
||||
double speedNotes = ((Speed)skills[2]).RelevantNoteCount();
|
||||
double flashlightRating = Math.Sqrt(skills[3].DifficultyValue()) * difficulty_multiplier;
|
||||
|
||||
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
|
||||
@ -75,6 +76,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
Mods = mods,
|
||||
AimDifficulty = aimRating,
|
||||
SpeedDifficulty = speedRating,
|
||||
SpeedNoteCount = speedNotes,
|
||||
FlashlightDifficulty = flashlightRating,
|
||||
SliderFactor = sliderFactor,
|
||||
ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5,
|
||||
|
@ -163,8 +163,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
speedValue *= 1.0 + 0.04 * (12.0 - attributes.ApproachRate);
|
||||
}
|
||||
|
||||
// Calculate accuracy assuming the worst case scenario
|
||||
double relevantTotalDiff = totalHits - attributes.SpeedNoteCount;
|
||||
double relevantCountGreat = Math.Max(0, countGreat - relevantTotalDiff);
|
||||
double relevantCountOk = Math.Max(0, countOk - Math.Max(0, relevantTotalDiff - countGreat));
|
||||
double relevantCountMeh = Math.Max(0, countMeh - Math.Max(0, relevantTotalDiff - countGreat - countOk));
|
||||
double relevantAccuracy = attributes.SpeedNoteCount == 0 ? 0 : (relevantCountGreat * 6.0 + relevantCountOk * 2.0 + relevantCountMeh) / (attributes.SpeedNoteCount * 6.0);
|
||||
|
||||
// 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);
|
||||
speedValue *= (0.95 + Math.Pow(attributes.OverallDifficulty, 2) / 750) * Math.Pow((accuracy + relevantAccuracy) / 2.0, (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);
|
||||
|
@ -8,6 +8,8 @@ using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Difficulty.Evaluators;
|
||||
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
{
|
||||
@ -26,6 +28,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
protected override double DifficultyMultiplier => 1.04;
|
||||
private readonly double greatWindow;
|
||||
|
||||
private readonly List<double> objectStrains = new List<double>();
|
||||
|
||||
public Speed(Mod[] mods, double hitWindowGreat)
|
||||
: base(mods)
|
||||
{
|
||||
@ -43,7 +47,24 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
||||
|
||||
currentRhythm = RhythmEvaluator.EvaluateDifficultyOf(current, greatWindow);
|
||||
|
||||
return currentStrain * currentRhythm;
|
||||
double totalStrain = currentStrain * currentRhythm;
|
||||
|
||||
objectStrains.Add(totalStrain);
|
||||
|
||||
return totalStrain;
|
||||
}
|
||||
|
||||
public double RelevantNoteCount()
|
||||
{
|
||||
if (objectStrains.Count == 0)
|
||||
return 0;
|
||||
|
||||
double maxStrain = objectStrains.Max();
|
||||
|
||||
if (maxStrain == 0)
|
||||
return 0;
|
||||
|
||||
return objectStrains.Aggregate((total, next) => total + (1.0 / (1.0 + Math.Exp(-(next / maxStrain * 12.0 - 6.0)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ namespace osu.Game.Rulesets.Difficulty
|
||||
protected const int ATTRIB_ID_SCORE_MULTIPLIER = 15;
|
||||
protected const int ATTRIB_ID_FLASHLIGHT = 17;
|
||||
protected const int ATTRIB_ID_SLIDER_FACTOR = 19;
|
||||
protected const int ATTRIB_ID_SPEED_NOTE_COUNT = 21;
|
||||
|
||||
/// <summary>
|
||||
/// The mods which were applied to the beatmap.
|
||||
|
Loading…
Reference in New Issue
Block a user