mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 06:57:39 +08:00
Update with latest changes
This commit is contained in:
parent
d04da46522
commit
9461097b00
@ -2,6 +2,8 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Difficulty.Skills;
|
||||
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
|
||||
@ -12,130 +14,108 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
|
||||
public class Colour : Skill
|
||||
{
|
||||
protected override double SkillMultiplier => 1;
|
||||
protected override double StrainDecayBase => 0.3;
|
||||
protected override double StrainDecayBase => 0.4;
|
||||
|
||||
private ColourSwitch lastColourSwitch = ColourSwitch.None;
|
||||
private int sameColourCount = 1;
|
||||
private bool prevIsKat = false;
|
||||
|
||||
private readonly int[] previousDonLengths = { 0, 0 };
|
||||
private readonly int[] previousKatLengths = { 0, 0 };
|
||||
private int currentMonoLength = 1;
|
||||
private List<int> monoHistory = new List<int>();
|
||||
private readonly int mono_history_max_length = 5;
|
||||
private int monoHistoryLength = 0;
|
||||
|
||||
private int sameTypeCount = 1;
|
||||
private double sameParityPenalty()
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// TODO: make this smarter (dont initialise with "Don")
|
||||
private bool previousIsKat;
|
||||
private double repititionPenalty(int notesSince)
|
||||
{
|
||||
double d = notesSince;
|
||||
return Math.Atan(d / 30) / (Math.PI / 2);
|
||||
}
|
||||
|
||||
private double patternLengthPenalty(int patternLength)
|
||||
{
|
||||
double shortPatternPenalty = Math.Min(0.25 * patternLength, 1.0);
|
||||
double longPatternPenalty = Math.Max(Math.Min(2.5 - 0.15 * patternLength, 1.0), 0.0);
|
||||
return Math.Min(shortPatternPenalty, longPatternPenalty);
|
||||
}
|
||||
|
||||
protected override double StrainValueOf(DifficultyHitObject current)
|
||||
{
|
||||
return StrainValueOfNew(current);
|
||||
}
|
||||
double objectDifficulty = 0.0;
|
||||
|
||||
protected double StrainValueOfNew(DifficultyHitObject current)
|
||||
{
|
||||
double returnVal = 0.0;
|
||||
double returnMultiplier = 1.0;
|
||||
|
||||
if (previousIsKat != ((TaikoDifficultyHitObject)current).IsKat)
|
||||
{
|
||||
returnVal = 1.5 - (1.75 / (sameTypeCount + 0.65));
|
||||
|
||||
if (previousIsKat)
|
||||
{
|
||||
if (sameTypeCount % 2 == previousDonLengths[0] % 2)
|
||||
{
|
||||
returnMultiplier *= 0.8;
|
||||
}
|
||||
|
||||
if (previousKatLengths[0] == sameTypeCount)
|
||||
{
|
||||
returnMultiplier *= 0.525;
|
||||
}
|
||||
|
||||
if (previousKatLengths[1] == sameTypeCount)
|
||||
{
|
||||
returnMultiplier *= 0.75;
|
||||
}
|
||||
|
||||
previousKatLengths[1] = previousKatLengths[0];
|
||||
previousKatLengths[0] = sameTypeCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sameTypeCount % 2 == previousKatLengths[0] % 2)
|
||||
{
|
||||
returnMultiplier *= 0.8;
|
||||
}
|
||||
|
||||
if (previousDonLengths[0] == sameTypeCount)
|
||||
{
|
||||
returnMultiplier *= 0.525;
|
||||
}
|
||||
|
||||
if (previousDonLengths[1] == sameTypeCount)
|
||||
{
|
||||
returnMultiplier *= 0.75;
|
||||
}
|
||||
|
||||
previousDonLengths[1] = previousDonLengths[0];
|
||||
previousDonLengths[0] = sameTypeCount;
|
||||
}
|
||||
|
||||
sameTypeCount = 1;
|
||||
previousIsKat = ((TaikoDifficultyHitObject)current).IsKat;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
sameTypeCount += 1;
|
||||
}
|
||||
|
||||
return Math.Min(1.25, returnVal) * returnMultiplier;
|
||||
}
|
||||
|
||||
protected double StrainValueOfOld(DifficultyHitObject current)
|
||||
{
|
||||
double addition = 0;
|
||||
|
||||
// We get an extra addition if we are not a slider or spinner
|
||||
if (current.LastObject is Hit && current.BaseObject is Hit && current.DeltaTime < 1000)
|
||||
{
|
||||
if (hasColourChange(current))
|
||||
addition = 0.75;
|
||||
|
||||
TaikoDifficultyHitObject currentHO = (TaikoDifficultyHitObject)current;
|
||||
|
||||
if (currentHO.IsKat == prevIsKat)
|
||||
{
|
||||
currentMonoLength += 1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
objectDifficulty = 1.0;
|
||||
|
||||
if (monoHistoryLength > 0 && (monoHistory[monoHistoryLength - 1] + currentMonoLength) % 2 == 0)
|
||||
{
|
||||
objectDifficulty *= sameParityPenalty();
|
||||
}
|
||||
|
||||
monoHistory.Add(currentMonoLength);
|
||||
monoHistoryLength += 1;
|
||||
|
||||
if (monoHistoryLength > mono_history_max_length)
|
||||
{
|
||||
monoHistory.RemoveAt(0);
|
||||
monoHistoryLength -= 1;
|
||||
}
|
||||
|
||||
for (int l = 2; l <= mono_history_max_length / 2; l++)
|
||||
{
|
||||
for (int start = monoHistoryLength - l - 1; start >= 0; start--)
|
||||
{
|
||||
bool samePattern = true;
|
||||
|
||||
for (int i = 0; i < l; i++)
|
||||
{
|
||||
if (monoHistory[start + i] != monoHistory[monoHistoryLength - l + i])
|
||||
{
|
||||
samePattern = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (samePattern) // Repitition found!
|
||||
{
|
||||
int notesSince = 0;
|
||||
for (int i = start; i < monoHistoryLength; i++) notesSince += monoHistory[i];
|
||||
objectDifficulty *= repititionPenalty(notesSince);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
currentMonoLength = 1;
|
||||
prevIsKat = currentHO.IsKat;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
|
||||
/*
|
||||
string path = @"out.txt";
|
||||
using (StreamWriter sw = File.AppendText(path))
|
||||
{
|
||||
lastColourSwitch = ColourSwitch.None;
|
||||
sameColourCount = 1;
|
||||
if (((TaikoDifficultyHitObject)current).IsKat) sw.WriteLine("k " + Math.Min(1.25, returnVal) * returnMultiplier);
|
||||
else sw.WriteLine("d " + Math.Min(1.25, returnVal) * returnMultiplier);
|
||||
}
|
||||
*/
|
||||
|
||||
return addition;
|
||||
return objectDifficulty;
|
||||
}
|
||||
|
||||
private bool hasColourChange(DifficultyHitObject current)
|
||||
{
|
||||
var taikoCurrent = (TaikoDifficultyHitObject)current;
|
||||
|
||||
if (!taikoCurrent.HasTypeChange)
|
||||
{
|
||||
sameColourCount++;
|
||||
return false;
|
||||
}
|
||||
|
||||
var oldColourSwitch = lastColourSwitch;
|
||||
var newColourSwitch = sameColourCount % 2 == 0 ? ColourSwitch.Even : ColourSwitch.Odd;
|
||||
|
||||
lastColourSwitch = newColourSwitch;
|
||||
sameColourCount = 1;
|
||||
|
||||
// We only want a bonus if the parity of the color switch changes
|
||||
return oldColourSwitch != ColourSwitch.None && oldColourSwitch != newColourSwitch;
|
||||
}
|
||||
|
||||
private enum ColourSwitch
|
||||
{
|
||||
None,
|
||||
Even,
|
||||
Odd
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,9 +49,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
|
||||
// Penalty for notes so slow that alting is not necessary.
|
||||
private double speedPenalty(double noteLengthMS)
|
||||
{
|
||||
|
||||
if (noteLengthMS < 80) return 1;
|
||||
if (noteLengthMS < 160) return Math.Max(0, 1.4 - 0.005 * noteLengthMS);
|
||||
if (noteLengthMS < 300) return 0.6;
|
||||
// return Math.Max(0, 1.4 - 0.005 * noteLengthMS);
|
||||
if (noteLengthMS < 210) return Math.Max(0, 1.4 - 0.005 * noteLengthMS);
|
||||
if (noteLengthMS < 210) return 0.6;
|
||||
|
||||
currentStrain = 0.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,10 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
{
|
||||
public class TaikoDifficultyAttributes : DifficultyAttributes
|
||||
{
|
||||
public double StaminaStrain;
|
||||
public double RhythmStrain;
|
||||
public double ColourStrain;
|
||||
public double ApproachRate;
|
||||
public double GreatHitWindow;
|
||||
public int MaxCombo;
|
||||
}
|
||||
|
@ -29,10 +29,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
{
|
||||
}
|
||||
|
||||
private double readingPenalty(double staminaDifficulty)
|
||||
private double simpleColourPenalty(double staminaDifficulty, double colorDifficulty)
|
||||
{
|
||||
return Math.Max(0, 1 - staminaDifficulty / 14);
|
||||
// return 1;
|
||||
return 0.79 - Math.Atan(staminaDifficulty / colorDifficulty - 12) / Math.PI / 2;
|
||||
}
|
||||
|
||||
private double norm(double p, double v1, double v2, double v3)
|
||||
@ -48,15 +47,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
{
|
||||
if (sr <= 1) return sr;
|
||||
sr -= 1;
|
||||
sr = 1.5 * Math.Pow(sr, 0.76);
|
||||
sr = 1.6 * Math.Pow(sr, 0.7);
|
||||
sr += 1;
|
||||
return sr;
|
||||
}
|
||||
|
||||
private double combinedDifficulty(Skill colour, Skill rhythm, Skill stamina1, Skill stamina2)
|
||||
private double combinedDifficulty(double staminaPenalty, Skill colour, Skill rhythm, Skill stamina1, Skill stamina2)
|
||||
{
|
||||
double staminaRating = (stamina1.DifficultyValue() + stamina2.DifficultyValue()) * staminaSkillMultiplier;
|
||||
double readingPenalty = this.readingPenalty(staminaRating);
|
||||
|
||||
double difficulty = 0;
|
||||
double weight = 1;
|
||||
@ -64,9 +61,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
|
||||
for (int i = 0; i < colour.StrainPeaks.Count; i++)
|
||||
{
|
||||
double colourPeak = colour.StrainPeaks[i] * colourSkillMultiplier * readingPenalty;
|
||||
double colourPeak = colour.StrainPeaks[i] * colourSkillMultiplier;
|
||||
double rhythmPeak = rhythm.StrainPeaks[i] * rhythmSkillMultiplier;
|
||||
double staminaPeak = (stamina1.StrainPeaks[i] + stamina2.StrainPeaks[i]) * staminaSkillMultiplier;
|
||||
double staminaPeak = (stamina1.StrainPeaks[i] + stamina2.StrainPeaks[i]) * staminaSkillMultiplier * staminaPenalty;
|
||||
peaks.Add(norm(2, colourPeak, rhythmPeak, staminaPeak));
|
||||
}
|
||||
|
||||
@ -85,11 +82,13 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
return new TaikoDifficultyAttributes { Mods = mods, Skills = skills };
|
||||
|
||||
double staminaRating = (skills[2].DifficultyValue() + skills[3].DifficultyValue()) * staminaSkillMultiplier;
|
||||
double readingPenalty = this.readingPenalty(staminaRating);
|
||||
|
||||
double colourRating = skills[0].DifficultyValue() * colourSkillMultiplier * readingPenalty;
|
||||
double colourRating = skills[0].DifficultyValue() * colourSkillMultiplier;
|
||||
double rhythmRating = skills[1].DifficultyValue() * rhythmSkillMultiplier;
|
||||
double combinedRating = combinedDifficulty(skills[0], skills[1], skills[2], skills[3]);
|
||||
|
||||
double staminaPenalty = simpleColourPenalty(staminaRating, colourRating);
|
||||
staminaRating *= staminaPenalty;
|
||||
|
||||
double combinedRating = combinedDifficulty(staminaPenalty, skills[0], skills[1], skills[2], skills[3]);
|
||||
|
||||
// Console.WriteLine("colour\t" + colourRating);
|
||||
// Console.WriteLine("rhythm\t" + rhythmRating);
|
||||
@ -107,6 +106,9 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
{
|
||||
StarRating = starRating,
|
||||
Mods = mods,
|
||||
StaminaStrain = staminaRating,
|
||||
RhythmStrain = rhythmRating,
|
||||
ColourStrain = colourRating,
|
||||
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
||||
GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate,
|
||||
MaxCombo = beatmap.HitObjects.Count(h => h is Hit),
|
||||
|
Loading…
Reference in New Issue
Block a user