mirror of
https://github.com/ppy/osu.git
synced 2024-12-18 08:42:56 +08:00
Adjust max history by clockrate to make rhythm calculation more consistent between rates
This commit is contained in:
parent
ce8286d299
commit
ed45c947fc
@ -60,12 +60,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
}
|
}
|
||||||
|
|
||||||
private const int history_time_max = 5 * 1000; // 5 seconds of calculatingRhythmBonus max.
|
private const int history_time_max = 5 * 1000; // 5 seconds of calculatingRhythmBonus max.
|
||||||
private const double rhythm_multiplier = 0.95;
|
private const int history_objects_max = 32;
|
||||||
|
private const double rhythm_multiplier = 1.25;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current <see cref="OsuDifficultyHitObject"/>.
|
/// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current <see cref="OsuDifficultyHitObject"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static double EvaluateDifficultyOf(DifficultyHitObject current)
|
public static double EvaluateDifficultyOf(DifficultyHitObject current, double clockRate)
|
||||||
{
|
{
|
||||||
if (current.BaseObject is Spinner)
|
if (current.BaseObject is Spinner)
|
||||||
return 0;
|
return 0;
|
||||||
@ -76,15 +77,18 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
var previousIsland = new Island();
|
var previousIsland = new Island();
|
||||||
Dictionary<Island, int> islandCounts = new Dictionary<Island, int>();
|
Dictionary<Island, int> islandCounts = new Dictionary<Island, int>();
|
||||||
|
|
||||||
|
int historyTimeMaxAdjusted = (int)Math.Ceiling(history_time_max / clockRate);
|
||||||
|
int historyObjectsMaxAdjusted = (int)Math.Ceiling(history_objects_max / clockRate);
|
||||||
|
|
||||||
double startRatio = 0; // store the ratio of the current start of an island to buff for tighter rhythms
|
double startRatio = 0; // store the ratio of the current start of an island to buff for tighter rhythms
|
||||||
|
|
||||||
bool firstDeltaSwitch = false;
|
bool firstDeltaSwitch = false;
|
||||||
|
|
||||||
int historicalNoteCount = Math.Min(current.Index, 32);
|
int historicalNoteCount = Math.Min(current.Index, historyObjectsMaxAdjusted);
|
||||||
|
|
||||||
int rhythmStart = 0;
|
int rhythmStart = 0;
|
||||||
|
|
||||||
while (rhythmStart < historicalNoteCount - 2 && current.StartTime - current.Previous(rhythmStart).StartTime < history_time_max)
|
while (rhythmStart < historicalNoteCount - 2 && current.StartTime - current.Previous(rhythmStart).StartTime < historyTimeMaxAdjusted)
|
||||||
rhythmStart++;
|
rhythmStart++;
|
||||||
|
|
||||||
OsuDifficultyHitObject prevObj = (OsuDifficultyHitObject)current.Previous(rhythmStart);
|
OsuDifficultyHitObject prevObj = (OsuDifficultyHitObject)current.Previous(rhythmStart);
|
||||||
@ -94,7 +98,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
{
|
{
|
||||||
OsuDifficultyHitObject currObj = (OsuDifficultyHitObject)current.Previous(i - 1);
|
OsuDifficultyHitObject currObj = (OsuDifficultyHitObject)current.Previous(i - 1);
|
||||||
|
|
||||||
double currHistoricalDecay = (history_time_max - (current.StartTime - currObj.StartTime)) / history_time_max; // scales note 0 to 1 from history to now
|
double currHistoricalDecay = (historyTimeMaxAdjusted - (current.StartTime - currObj.StartTime)) / historyTimeMaxAdjusted; // scales note 0 to 1 from history to now
|
||||||
|
|
||||||
currHistoricalDecay = Math.Min((double)(historicalNoteCount - i) / historicalNoteCount, currHistoricalDecay); // either we're limited by time or limited by object count.
|
currHistoricalDecay = Math.Min((double)(historicalNoteCount - i) / historicalNoteCount, currHistoricalDecay); // either we're limited by time or limited by object count.
|
||||||
|
|
||||||
@ -102,16 +106,14 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
double prevDelta = prevObj.StrainTime;
|
double prevDelta = prevObj.StrainTime;
|
||||||
double lastDelta = lastObj.StrainTime;
|
double lastDelta = lastObj.StrainTime;
|
||||||
|
|
||||||
double currRatio = 1.0 + 9.8 * Math.Min(0.5, Math.Pow(Math.Sin(Math.PI / (Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta))), 2)); // fancy function to calculate rhythmbonuses.
|
double currRatio = 1.0 + 7.27 * Math.Min(0.5, Math.Pow(Math.Sin(Math.PI / (Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta))), 2)); // fancy function to calculate rhythmbonuses.
|
||||||
|
|
||||||
double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - currObj.HitWindowGreat * 0.3) / (currObj.HitWindowGreat * 0.3));
|
|
||||||
|
|
||||||
windowPenalty = Math.Min(1, windowPenalty);
|
|
||||||
|
|
||||||
double effectiveRatio = windowPenalty * currRatio;
|
|
||||||
|
|
||||||
double deltaDifferenceEpsilon = currObj.HitWindowGreat * 0.3;
|
double deltaDifferenceEpsilon = currObj.HitWindowGreat * 0.3;
|
||||||
|
|
||||||
|
double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - deltaDifferenceEpsilon) / deltaDifferenceEpsilon);
|
||||||
|
|
||||||
|
double effectiveRatio = windowPenalty * currRatio;
|
||||||
|
|
||||||
if (firstDeltaSwitch)
|
if (firstDeltaSwitch)
|
||||||
{
|
{
|
||||||
if (!(Math.Abs(prevDelta - currDelta) > deltaDifferenceEpsilon))
|
if (!(Math.Abs(prevDelta - currDelta) > deltaDifferenceEpsilon))
|
||||||
@ -145,7 +147,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
|
|
||||||
// repeated island (ex: triplet -> triplet)
|
// repeated island (ex: triplet -> triplet)
|
||||||
double power = logistic(island.AverageDelta(), 4, 0.165, 10);
|
double power = logistic(island.AverageDelta(), 4, 0.165, 10);
|
||||||
effectiveRatio *= Math.Min(2.0 / islandCounts[island], Math.Pow(1.0 / islandCounts[island], power));
|
effectiveRatio *= Math.Min(3.0 / islandCounts[island], Math.Pow(1.0 / islandCounts[island], power));
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale down the difficulty if the object is doubletappable
|
// scale down the difficulty if the object is doubletappable
|
||||||
|
@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
{
|
{
|
||||||
new Aim(mods, true),
|
new Aim(mods, true),
|
||||||
new Aim(mods, false),
|
new Aim(mods, false),
|
||||||
new Speed(mods)
|
new Speed(mods, clockRate)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mods.Any(h => h is OsuModFlashlight))
|
if (mods.Any(h => h is OsuModFlashlight))
|
||||||
|
@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Speed : OsuStrainSkill
|
public class Speed : OsuStrainSkill
|
||||||
{
|
{
|
||||||
|
private readonly double clockRate;
|
||||||
private double skillMultiplier => 1375;
|
private double skillMultiplier => 1375;
|
||||||
private double strainDecayBase => 0.3;
|
private double strainDecayBase => 0.3;
|
||||||
|
|
||||||
@ -27,9 +28,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
|||||||
|
|
||||||
private readonly List<double> objectStrains = new List<double>();
|
private readonly List<double> objectStrains = new List<double>();
|
||||||
|
|
||||||
public Speed(Mod[] mods)
|
public Speed(Mod[] mods, double clockRate)
|
||||||
: base(mods)
|
: base(mods)
|
||||||
{
|
{
|
||||||
|
this.clockRate = clockRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000);
|
private double strainDecay(double ms) => Math.Pow(strainDecayBase, ms / 1000);
|
||||||
@ -41,7 +43,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
|
|||||||
currentStrain *= strainDecay(((OsuDifficultyHitObject)current).StrainTime);
|
currentStrain *= strainDecay(((OsuDifficultyHitObject)current).StrainTime);
|
||||||
currentStrain += SpeedEvaluator.EvaluateDifficultyOf(current) * skillMultiplier;
|
currentStrain += SpeedEvaluator.EvaluateDifficultyOf(current) * skillMultiplier;
|
||||||
|
|
||||||
currentRhythm = RhythmEvaluator.EvaluateDifficultyOf(current);
|
currentRhythm = RhythmEvaluator.EvaluateDifficultyOf(current, clockRate);
|
||||||
|
|
||||||
double totalStrain = currentStrain * currentRhythm;
|
double totalStrain = currentStrain * currentRhythm;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user