Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Difficulty calculator rework #45

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,40 @@ namespace osu.Game.Rulesets.Soyokaze.Difficulty.Preprocessing
{
public class SoyokazeDifficultyHitObject : DifficultyHitObject
{
public const int COUNT = 8;
public const int MIN_COUNT = 2;
public const int MAX_COUNT = 8;

public SoyokazeAction Button = (SoyokazeAction)(-1);
public int Consecutive = 0;
public int ButtonVariety = 0;
public double TotalDeltaTime = 0.0;
public double ConsecutiveDeltaTime = 0.0;
public int ButtonVariety;
public double TotalDeltaTime;
public double ConsecutiveDeltaTime;

public SoyokazeDifficultyHitObject(double clockRate, HitObject[] hitObjects, List<DifficultyHitObject> diffObjects, int index)
: base(hitObjects[COUNT - 1], hitObjects[COUNT - 2], clockRate, diffObjects, index)
: base(hitObjects[^1], hitObjects[^2], clockRate, diffObjects, index)
{
Button = (hitObjects[COUNT - 1] as SoyokazeHitObject).Button;
Button = (hitObjects[^1] as SoyokazeHitObject).Button;

for (int i = hitObjects.Length - 1; i >= 0; i--)
bool[] counted = new bool[8];
for (int i = 0; i < hitObjects.Length; i++)
{
if ((hitObjects[i] as SoyokazeHitObject).Button != Button)
break;
Consecutive++;
if (!(hitObjects[i] is SoyokazeHitObject obj) || counted[(int)obj.Button])
continue;

counted[(int)obj.Button] = true;
ButtonVariety++;
}

bool[] counted = new bool[COUNT];
foreach (SoyokazeHitObject hitObject in hitObjects)
SoyokazeHitObject lastConsecutive = null;
for (int i = 2; i < hitObjects.Length; i++)
{
if (counted[(int)hitObject.Button])
if (!(hitObjects[^i] is SoyokazeHitObject obj) || obj.Button != Button)
continue;
counted[(int)hitObject.Button] = true;
ButtonVariety++;
}

TotalDeltaTime = Math.Max((hitObjects[COUNT - 1].StartTime - hitObjects[0].StartTime) / clockRate, 1);
ConsecutiveDeltaTime = Math.Max((hitObjects[COUNT - 1].StartTime - hitObjects[COUNT - Consecutive].StartTime) / clockRate, 1);
lastConsecutive = obj;
break;
}
TotalDeltaTime = Math.Max((hitObjects[^1].StartTime - hitObjects[0].StartTime) / clockRate, 1);
ConsecutiveDeltaTime = Math.Max((hitObjects[^1].StartTime - lastConsecutive?.StartTime ?? -1e6) / clockRate, 1);
}
}
}
5 changes: 2 additions & 3 deletions osu.Game.Rulesets.Soyokaze/Difficulty/Skills/SkillRead.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ namespace osu.Game.Rulesets.Soyokaze.Difficulty.Skills
{
public class SkillRead : StrainDecaySkill
{
// slow decay and medium multiplier = buff consistently fast and cluttered maps
protected override double SkillMultiplier => 7.0;
protected override double StrainDecayBase => 0.3;
protected override double SkillMultiplier => 1.59;
protected override double StrainDecayBase => 0.08;

public SkillRead(Mod[] mods)
: base(mods)
Expand Down
11 changes: 4 additions & 7 deletions osu.Game.Rulesets.Soyokaze/Difficulty/Skills/SkillSpeed.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Alden Wu <aldenwu0@gmail.com>. Licensed under the MIT Licence.
// See the LICENSE file in the repository root for full licence text.

using System;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods;
Expand All @@ -10,9 +11,8 @@ namespace osu.Game.Rulesets.Soyokaze.Difficulty.Skills
{
public class SkillSpeed : StrainDecaySkill
{
// fast decay and high multiplier = buff short and fast bursts/triples
protected override double SkillMultiplier => 13.5;
protected override double StrainDecayBase => 0.115;
protected override double SkillMultiplier => 0.85;
protected override double StrainDecayBase => 0.71;

public SkillSpeed(Mod[] mods)
: base(mods)
Expand All @@ -23,10 +23,7 @@ protected override double StrainValueOf(DifficultyHitObject current)
{
SoyokazeDifficultyHitObject soyokazeObject = current as SoyokazeDifficultyHitObject;

if (soyokazeObject.Consecutive < 2)
return 0;

return SkillMultiplier * (soyokazeObject.Consecutive - 1) / soyokazeObject.ConsecutiveDeltaTime;
return SkillMultiplier / Math.Pow(soyokazeObject.ConsecutiveDeltaTime, 0.32);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Logging;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Difficulty.Preprocessing;
Expand All @@ -19,6 +20,12 @@ public class SoyokazeDifficultyCalculator : DifficultyCalculator
{
private const double difficulty_multiplier = 0.445;

// SR values which are good and should be exponentially curved between
private const double x1 = 1.3;
private const double x2 = 6.8;
private static readonly double k = Math.Pow(x1, x2 / (x2 - x1)) * Math.Pow(x2, x1 / (x1 - x2));
private static readonly double a = Math.Pow(x1 / x2, 1 / (x1 - x2));

public SoyokazeDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
: base(ruleset, beatmap)
{
Expand All @@ -34,27 +41,29 @@ protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beat

double speedRating = Math.Sqrt(skills[0].DifficultyValue()) * difficulty_multiplier;
double readRating = Math.Sqrt(skills[1].DifficultyValue()) * difficulty_multiplier;
double baseStarRating = speedRating + readRating + (speedRating - readRating) / 3;

double starRating = speedRating + readRating + (speedRating - readRating) / 3;

int maxCombo = beatmap.HitObjects.Count;
double starRating = k * Math.Pow(a, baseStarRating);

return new SoyokazeDifficultyAttributes
{
StarRating = starRating,
Mods = mods,
MaxCombo = maxCombo,
MaxCombo = beatmap.HitObjects.Count,
};
}

protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate)
{
var diffObjects = new List<DifficultyHitObject>();

for (int i = 0; i < beatmap.HitObjects.Count - SoyokazeDifficultyHitObject.COUNT; i++)
for (int i = SoyokazeDifficultyHitObject.MIN_COUNT; i <= beatmap.HitObjects.Count; i++)
{
var hitObjects = beatmap.HitObjects.Skip(i).Take(SoyokazeDifficultyHitObject.COUNT).ToArray();
var diffObject = new SoyokazeDifficultyHitObject(clockRate, hitObjects, diffObjects, i);
int begin = Math.Max(0, i - SoyokazeDifficultyHitObject.MAX_COUNT);
int end = i;
var hitObjects = beatmap.HitObjects.Skip(begin).Take(end - begin).ToArray();
var diffObject = new SoyokazeDifficultyHitObject(clockRate, hitObjects, diffObjects, i - SoyokazeDifficultyHitObject.MIN_COUNT);

diffObjects.Add(diffObject);
}

Expand Down