diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs
index 4372ed938c..cfb3fe40be 100644
--- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs
+++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs
@@ -9,7 +9,7 @@ using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Difficulty.Skills
{
- public class Movement : StrainSkill
+ public class Movement : StrainDecaySkill
{
private const float absolute_player_positioning_error = 16f;
private const float normalized_hitobject_radius = 41.0f;
diff --git a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs
index 2ba2ee6b4a..01d930d585 100644
--- a/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs
+++ b/osu.Game.Rulesets.Mania/Difficulty/Skills/Strain.cs
@@ -10,7 +10,7 @@ using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Difficulty.Skills
{
- public class Strain : StrainSkill
+ public class Strain : StrainDecaySkill
{
private const double individual_decay_base = 0.125;
private const double overall_decay_base = 0.30;
@@ -71,7 +71,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
return individualStrain + overallStrain - CurrentStrain;
}
- protected override double GetPeakStrain(double offset)
+ protected override double CalculateInitialStrain(double offset)
=> applyDecay(individualStrain, offset - Previous[0].StartTime, individual_decay_base)
+ applyDecay(overallStrain, offset - Previous[0].StartTime, overall_decay_base);
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
index 16a18cbcb9..f08c19af76 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
///
/// Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances.
///
- public class Aim : OsuStrainSkill
+ public class Aim : OsuStrainDecaySkill
{
private const double angle_bonus_begin = Math.PI / 3;
private const double timing_threshold = 107;
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index e47edc37cc..c1bee9b202 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -10,7 +10,7 @@ using osu.Framework.Utils;
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
{
- public abstract class OsuStrainSkill : StrainSkill
+ public abstract class OsuStrainDecaySkill : StrainDecaySkill
{
///
/// The number of sections with the highest strains, which the peak strain reductions will apply to.
@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
///
protected virtual double DifficultyMultiplier => 1.06;
- protected OsuStrainSkill(Mod[] mods)
+ protected OsuStrainDecaySkill(Mod[] mods)
: base(mods)
{
}
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 433150a025..bb40ff657a 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
///
/// Represents the skill required to press keys with regards to keeping up with the speed at which objects need to be hit.
///
- public class Speed : OsuStrainSkill
+ public class Speed : OsuStrainDecaySkill
{
private const double single_spacing_threshold = 125;
@@ -151,14 +151,5 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return (1 + (speedBonus - 1) * 0.75) * angleBonus * (0.95 + speedBonus * Math.Pow(distance / single_spacing_threshold, 3.5)) / osuCurrent.StrainTime;
}
- protected override double GetTotalCurrentStrain(DifficultyHitObject current)
- {
- return base.GetTotalCurrentStrain(current) * calculateRhythmBonus(current.StartTime);
- }
-
- protected override double GetPeakStrain(double time)
- {
- return base.GetPeakStrain(time);// * calculateRhythmBonus(current.StartTime);
- }
}
}
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs
index 769d021362..0c17ca66b9 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
///
/// Calculates the colour coefficient of taiko difficulty.
///
- public class Colour : StrainSkill
+ public class Colour : StrainDecaySkill
{
protected override double SkillMultiplier => 1;
protected override double StrainDecayBase => 0.4;
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs
index a32f6ebe0d..973e55f4b4 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Rhythm.cs
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
///
/// Calculates the rhythm coefficient of taiko difficulty.
///
- public class Rhythm : StrainSkill
+ public class Rhythm : StrainDecaySkill
{
protected override double SkillMultiplier => 10;
protected override double StrainDecayBase => 0;
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs
index 4cceadb23f..54cf233d69 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs
@@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
///
/// The reference play style chosen uses two hands, with full alternating (the hand changes after every hit).
///
- public class Stamina : StrainSkill
+ public class Stamina : StrainDecaySkill
{
protected override double SkillMultiplier => 1;
protected override double StrainDecayBase => 0.4;
diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs
new file mode 100644
index 0000000000..dab1081abb
--- /dev/null
+++ b/osu.Game/Rulesets/Difficulty/Skills/StrainDecaySkill.cs
@@ -0,0 +1,64 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using osu.Game.Rulesets.Difficulty.Preprocessing;
+using osu.Game.Rulesets.Mods;
+
+namespace osu.Game.Rulesets.Difficulty.Skills
+{
+ ///
+ /// Used to processes strain values of s, keep track of strain levels caused by the processed objects
+ /// and to calculate a final difficulty value representing the difficulty of hitting all the processed objects.
+ ///
+ public abstract class StrainDecaySkill : StrainSkill
+ {
+ ///
+ /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other.
+ ///
+ protected abstract double SkillMultiplier { get; }
+
+ ///
+ /// Determines how quickly strain decays for the given skill.
+ /// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second.
+ ///
+ protected abstract double StrainDecayBase { get; }
+
+ ///
+ /// The current strain level.
+ ///
+ protected double CurrentStrain { get; private set; } = 1;
+
+ protected StrainDecaySkill(Mod[] mods)
+ : base(mods)
+ {
+ }
+
+ ///
+ /// Retrieves the peak strain at a point in time.
+ ///
+ /// The time to retrieve the peak strain at.
+ /// The peak strain.
+ protected override double CalculateInitialStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime);
+
+ ///
+ /// Returns the strain value of . This value is calculated with or without respect to previous objects.
+ ///
+ protected override double StrainValueAt(DifficultyHitObject current)
+ {
+ CurrentStrain *= strainDecay(current.DeltaTime);
+ CurrentStrain += StrainValueOf(current) * SkillMultiplier;
+
+ return CurrentStrain;
+ }
+
+ ///
+ /// Calculates the strain value of a . This value is affected by previously processed objects.
+ ///
+ protected abstract double StrainValueOf(DifficultyHitObject current);
+
+ private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000);
+ }
+}
diff --git a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs
index 95b0fe43fc..e8ae452506 100644
--- a/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs
+++ b/osu.Game/Rulesets/Difficulty/Skills/StrainSkill.cs
@@ -15,27 +15,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills
///
public abstract class StrainSkill : Skill
{
- ///
- /// Strain values are multiplied by this number for the given skill. Used to balance the value of different skills between each other.
- ///
- protected abstract double SkillMultiplier { get; }
-
- ///
- /// Determines how quickly strain decays for the given skill.
- /// For example a value of 0.15 indicates that strain decays to 15% of its original value in one second.
- ///
- protected abstract double StrainDecayBase { get; }
-
///
/// The weight by which each strain value decays.
///
protected virtual double DecayWeight => 0.9;
- ///
- /// The current strain level.
- ///
- protected double CurrentStrain { get; private set; } = 1;
-
///
/// The length of each strain section.
///
@@ -52,6 +36,11 @@ namespace osu.Game.Rulesets.Difficulty.Skills
{
}
+ ///
+ /// Returns the strain value of . This value is calculated with or without respect to previous objects.
+ ///
+ protected abstract double StrainValueAt(DifficultyHitObject current);
+
///
/// Process a and update current strain values accordingly.
///
@@ -68,15 +57,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills
currentSectionEnd += SectionLength;
}
- CurrentStrain *= strainDecay(current.DeltaTime);
- CurrentStrain += StrainValueOf(current) * SkillMultiplier;
-
- currentSectionPeak = Math.Max(GetTotalCurrentStrain(current), currentSectionPeak);
- }
-
- protected virtual double GetTotalCurrentStrain(DifficultyHitObject current)
- {
- return CurrentStrain;
+ currentSectionPeak = Math.Max(StrainValueAt(current), currentSectionPeak);
}
///
@@ -93,9 +74,9 @@ namespace osu.Game.Rulesets.Difficulty.Skills
/// The beginning of the new section in milliseconds.
private void startNewSectionFrom(double time)
{
- // The maximum strain of the new section is not zero by default, strain decays as usual regardless of section boundaries.
+ // The maximum strain of the new section is not zero by default
// This means we need to capture the strain level at the beginning of the new section, and use that as the initial peak level.
- currentSectionPeak = GetPeakStrain(time);
+ currentSectionPeak = CalculateInitialStrain(time);
}
///
@@ -103,7 +84,7 @@ namespace osu.Game.Rulesets.Difficulty.Skills
///
/// The time to retrieve the peak strain at.
/// The peak strain.
- protected virtual double GetPeakStrain(double time) => CurrentStrain * strainDecay(time - Previous[0].StartTime);
+ protected abstract double CalculateInitialStrain(double time);
///
/// Returns a live enumerable of the peak strains for each section of the beatmap,
@@ -129,12 +110,5 @@ namespace osu.Game.Rulesets.Difficulty.Skills
return difficulty;
}
-
- ///
- /// Calculates the strain value of a . This value is affected by previously processed objects.
- ///
- protected abstract double StrainValueOf(DifficultyHitObject current);
-
- private double strainDecay(double ms) => Math.Pow(StrainDecayBase, ms / 1000);
}
}