Skip to content

Commit

Permalink
DifficultyFactor LengthBonus calculation changed
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDark98 committed Jan 12, 2025
1 parent 4a5b0c5 commit b00e61f
Show file tree
Hide file tree
Showing 11 changed files with 46 additions and 103 deletions.
5 changes: 0 additions & 5 deletions osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ public override double DifficultyValue()

List<double> strains = peaks.OrderDescending().ToList();

foreach (double strain in strains.OrderDescending())
{
AddStrain(strain);
}

// We are reducing the highest strains first to account for extreme difficulty spikes
for (int i = 0; i < Math.Min(strains.Count, ReducedSectionCount); i++)
{
Expand Down
9 changes: 1 addition & 8 deletions osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@ public Colour(Mod[] mods)
{
}

protected override double StrainValueOf(DifficultyHitObject current)
{
double currentStrainValue = ColourEvaluator.EvaluateDifficultyOf(current);

AddStrain(currentStrainValue);

return currentStrainValue;
}
protected override double StrainValueOf(DifficultyHitObject current) => ColourEvaluator.EvaluateDifficultyOf(current);
}
}
6 changes: 1 addition & 5 deletions osu.Game.Rulesets.Taiko/Difficulty/Skills/Reading.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,8 @@ protected override double StrainValueOf(DifficultyHitObject current)
return 0.0;
}

double currentStrainValue = ReadingEvaluator.EvaluateDifficultyOf((TaikoDifficultyHitObject)current) * SkillMultiplier;

currentStrain *= StrainDecayBase;
currentStrain += currentStrainValue;

AddStrain(currentStrainValue);
currentStrain += ReadingEvaluator.EvaluateDifficultyOf((TaikoDifficultyHitObject)current) * SkillMultiplier;

return currentStrain;
}
Expand Down
2 changes: 0 additions & 2 deletions osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ protected override double StrainValueOf(DifficultyHitObject current)
// To prevent abuse of exceedingly long intervals between awkward rhythms, we penalise its difficulty.
difficulty *= DifficultyCalculationUtils.Logistic(current.DeltaTime, 350, -1 / 25.0, 0.5) + 0.5;

AddStrain(difficulty);

return difficulty;
}
}
Expand Down
5 changes: 1 addition & 4 deletions osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ public Stamina(Mod[] mods, bool singleColourStamina)

protected override double StrainValueAt(DifficultyHitObject current)
{
double currentStrainValue = StaminaEvaluator.EvaluateDifficultyOf(current) * skillMultiplier;

currentStrain *= strainDecay(current.DeltaTime);
currentStrain += currentStrainValue;

AddStrain(currentStrainValue);
currentStrain += StaminaEvaluator.EvaluateDifficultyOf(current) * skillMultiplier; ;

// Safely prevents previous strains from shifting as new notes are added.
var currentObject = current as TaikoDifficultyHitObject;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
{
public class TaikoDifficultyAttributes : DifficultyAttributes
{
/// <summary>
/// The difficulty corresponding to the rhythm skill.
/// </summary>
[JsonProperty("total_difficulty_factor")]
public double TotalDifficultyFactor { get; set; }

/// <summary>
/// The difficulty corresponding to the rhythm skill.
/// </summary>
Expand Down
60 changes: 23 additions & 37 deletions osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
using osu.Game.Rulesets.Taiko.Difficulty.Skills;
using osu.Game.Rulesets.Taiko.Mods;
using osu.Game.Rulesets.Taiko.Scoring;
using osuTK;

Check failure on line 22 in osu.Game.Rulesets.Taiko/Difficulty/TaikoDifficultyCalculator.cs

View workflow job for this annotation

GitHub Actions / Code Quality

Using directive is unnecessary. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/ide0005)
using SharpCompress;

namespace osu.Game.Rulesets.Taiko.Difficulty
{
Expand All @@ -30,8 +32,12 @@ public class TaikoDifficultyCalculator : DifficultyCalculator
private const double colour_skill_multiplier = 0.375 * difficulty_multiplier;
private const double stamina_skill_multiplier = 0.375 * difficulty_multiplier;

private const double hard_hit_multiplier = 1.5; //multiplier to balance spike weigth
private const double easy_hit_multiplier = 0.9; //multiplier to balance filler weigth
private const double bonus_offset = 1.0;
private const double bonus_multiplier = 0.3;


private double totalDifficultyFactor;
private double consistencyRequiredFactor;

public override int Version => 20241007;

Expand Down Expand Up @@ -119,45 +125,19 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat
double monoStaminaRating = singleColourStamina.DifficultyValue() * stamina_skill_multiplier;
double monoStaminaFactor = staminaRating == 0 ? 1 : Math.Pow(monoStaminaRating / staminaRating, 5);

double rhythmDifficultyFactor = rhythm.DifficultyFactor();
double staminaDifficultyFactor = stamina.DifficultyFactor();
double readingDifficultyFactor = reading.DifficultyFactor();
double colourDifficultyFactor = colour.DifficultyFactor();

double colourDifficultStrains = colour.CountTopWeightedStrains();
double readingDifficultStrains = reading.CountTopWeightedStrains();
double staminaDifficultStrains = stamina.CountTopWeightedStrains();

int HitObjects = beatmap.HitObjects.Count;

CalculateBaseLengthBonus(rhythmRating, rhythmDifficultyFactor, HitObjects);

double rhythmDifficultyLengthBonus = EasyLengthBonus * easy_hit_multiplier + HardLengthBonus * hard_hit_multiplier;

rhythmRating += rhythmDifficultyLengthBonus;

CalculateBaseLengthBonus(staminaRating, staminaDifficultyFactor, HitObjects);

double staminaDifficultyLengthBonus = EasyLengthBonus * easy_hit_multiplier + HardLengthBonus * hard_hit_multiplier;

staminaRating += staminaDifficultyLengthBonus;
consistencyRequiredFactor = (Math.Log(10.0 + beatmap.HitObjects.Count / 1000.0) - 1.35) * 0.45 + 0.5;

CalculateBaseLengthBonus(readingRating, readingDifficultyFactor, HitObjects);

double readingDifficultyLengthBonus = EasyLengthBonus * easy_hit_multiplier + HardLengthBonus * hard_hit_multiplier;

readingRating += readingDifficultyLengthBonus;

CalculateBaseLengthBonus(colourRating, colourDifficultyFactor, HitObjects);

double colourDifficultyLengthBonus = EasyLengthBonus * easy_hit_multiplier + HardLengthBonus * hard_hit_multiplier;

colourRating += colourDifficultyLengthBonus;
rhythmRating *= LengthBonusMultiplier(consistencyRequiredFactor, rhythm.DifficultyFactor, bonus_multiplier);
readingRating *= LengthBonusMultiplier(consistencyRequiredFactor, reading.DifficultyFactor, bonus_multiplier);
colourRating *= LengthBonusMultiplier(consistencyRequiredFactor, colour.DifficultyFactor, bonus_multiplier);
staminaRating *= LengthBonusMultiplier(consistencyRequiredFactor, stamina.DifficultyFactor, bonus_multiplier);

double combinedRating = combinedDifficultyValue(rhythm, reading, colour, stamina, isRelax);

combinedRating += (rhythmDifficultyLengthBonus + staminaDifficultyLengthBonus + readingDifficultyLengthBonus + colourDifficultyLengthBonus) / 4;

double starRating = rescale(combinedRating * 1.4);

// Converts are penalised outside the scope of difficulty calculation, as our assumptions surrounding standard play-styles becomes out-of-scope.
Expand All @@ -176,15 +156,16 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat
TaikoDifficultyAttributes attributes = new TaikoDifficultyAttributes
{
StarRating = starRating,
TotalDifficultyFactor = totalDifficultyFactor,
Mods = mods,
RhythmDifficulty = rhythmRating,
RhythmDifficultyFactor = rhythmDifficultyFactor,
RhythmDifficultyFactor = rhythm.DifficultyFactor,
ReadingDifficulty = readingRating,
ReadingDifficultyFactor = readingDifficultyFactor,
ReadingDifficultyFactor = reading.DifficultyFactor,
ColourDifficulty = colourRating,
ColourDifficultyFactor = colourDifficultyFactor,
ColourDifficultyFactor = colour.DifficultyFactor,
StaminaDifficulty = staminaRating,
StaminaDifficultyFactor = staminaDifficultyFactor,
StaminaDifficultyFactor = stamina.DifficultyFactor,
MonoStaminaFactor = monoStaminaFactor,
ReadingTopStrains = readingDifficultStrains,
ColourTopStrains = colourDifficultStrains,
Expand Down Expand Up @@ -243,6 +224,11 @@ private double combinedDifficultyValue(Rhythm rhythm, Reading reading, Colour co
weight *= 0.9;
}

totalDifficultyFactor = peaks.Average() / peaks.Max();

difficulty *= LengthBonusMultiplier(consistencyRequiredFactor, totalDifficultyFactor, bonus_multiplier);


return difficulty;
}

Expand Down
11 changes: 4 additions & 7 deletions osu.Game.Rulesets.Taiko/Difficulty/TaikoPerformanceCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ private double computeDifficultyValue(ScoreInfo score, TaikoDifficultyAttributes
if (score.Mods.Any(m => m is ModFlashlight<TaikoHitObject>))
difficultyValue *= Math.Max(1, 1.050 - Math.Min(attributes.MonoStaminaFactor / 50, 1));

difficultyValue *= Math.Pow(0.986, effectiveMissCount);
double realEffectiveMissCount = effectiveMissCount / (1.0 + attributes.TotalDifficultyFactor);

difficultyValue *= Math.Pow(0.986, realEffectiveMissCount);

if (score.Mods.Any(m => m is ModEasy))
difficultyValue *= 0.90;
Expand Down Expand Up @@ -164,12 +166,7 @@ private double computeAccuracyValue(ScoreInfo score, TaikoDifficultyAttributes a

double n = totalHits;

double avarageDifficultyFactor = attributes.ColourDifficultyFactor + attributes.ReadingDifficultyFactor + attributes.StaminaDifficultyFactor + attributes.RhythmDifficultyFactor;
avarageDifficultyFactor /= 4;

//double realCountOk = countOk / (0.84 + avarageDifficultyFactor * 0.2);

double realCountOk = countOk / avarageDifficultyFactor;
double realCountOk = countOk / (1.0 + attributes.TotalDifficultyFactor);

// Proportion of greats + goods hit.
double p = Math.Max(0, totalSuccessfulHits - realCountOk) / n;
Expand Down
16 changes: 2 additions & 14 deletions osu.Game/Rulesets/Difficulty/DifficultyCalculator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,10 @@ namespace osu.Game.Rulesets.Difficulty
{
public abstract class DifficultyCalculator
{
protected double HardLengthBonus; //Bonus PP for hard hits
protected double EasyLengthBonus; //Bonus PP for easy hits

/// <summary>
/// Calculate the bonus for that skill.
/// Calculate the length bonus divisor.
/// </summary>
protected void CalculateBaseLengthBonus(double basePP, double difficultyFactor, int totalHits)
{
basePP *= 0.0001;

double hardHits = totalHits * difficultyFactor;
double easyHits = totalHits - hardHits;

HardLengthBonus = basePP * hardHits; //Length bonus for hard hit with basePP * offset
EasyLengthBonus = basePP * easyHits; //Length bonus for easy hit with basePP * offset
}
protected virtual double LengthBonusMultiplier(double offsetLengthBonus, double difficultyFactor, double multiplierDifficultyFactor) => offsetLengthBonus + difficultyFactor * multiplierDifficultyFactor;

/// <summary>
/// The beatmap for which difficulty will be calculated.
Expand Down
10 changes: 5 additions & 5 deletions osu.Game/Rulesets/Difficulty/Skills/Skill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ protected Skill(Mod[] mods)
this.mods = mods;
}

/// <summary>
/// Factor value representing all <see cref="DifficultyHitObject"/>s / hardest one that have been processed up to this point.
/// </summary>
public double DifficultyFactor;

/// <summary>
/// Process a <see cref="DifficultyHitObject"/>.
/// </summary>
Expand All @@ -37,10 +42,5 @@ protected Skill(Mod[] mods)
/// Returns the calculated difficulty value representing all <see cref="DifficultyHitObject"/>s that have been processed up to this point.
/// </summary>
public abstract double DifficultyValue();

/// <summary>
/// Returns the factor difficulty value representing all <see cref="DifficultyHitObject"/>s that have been processed up to this point.
/// </summary>
public abstract double DifficultyFactor();
}
}
19 changes: 3 additions & 16 deletions osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ public abstract class StrainSkill : Skill
private double currentSectionPeak; // We also keep track of the peak strain level in the current section.
private double currentSectionEnd;

private double maxDifficulty; //Max difficulty of a single object

private double summedDifficulty; //Summed difficulty of a single object

protected double AddedStrain; //Summed difficulty of a single object

private readonly List<double> strainPeaks = new List<double>();
protected readonly List<double> ObjectStrains = new List<double>(); // Store individual strains

Expand Down Expand Up @@ -134,6 +128,9 @@ public override double DifficultyValue()
// These sections will not contribute to the difficulty.
var peaks = GetCurrentStrainPeaks().Where(p => p > 0);

DifficultyFactor = peaks.Average() / peaks.Max();


// Difficulty is the weighted sum of the highest strains from every section.
// We're sorting from highest to lowest strain.
foreach (double strain in peaks.OrderDescending())
Expand All @@ -144,15 +141,5 @@ public override double DifficultyValue()

return difficulty;
}

protected void AddStrain(double currentStrain)
{
summedDifficulty += currentStrain;

if (maxDifficulty < currentStrain)
maxDifficulty = currentStrain;
AddedStrain++;
}
public override double DifficultyFactor() => summedDifficulty / AddedStrain / maxDifficulty;
}
}

0 comments on commit b00e61f

Please sign in to comment.