osu/osu.Game.Rulesets.Taiko/Difficulty/Skills/Stamina.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

112 lines
3.5 KiB
C#
Raw Normal View History

2020-05-11 05:50:02 +00:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2022-05-10 08:17:40 +00:00
using System;
2020-05-11 05:50:02 +00:00
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Difficulty.Skills;
using osu.Game.Rulesets.Mods;
2020-05-11 05:50:02 +00:00
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
2020-06-08 07:30:26 +00:00
using osu.Game.Rulesets.Taiko.Objects;
2020-05-11 05:50:02 +00:00
namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
{
2022-05-10 08:17:40 +00:00
class SingleKeyStamina
{
private double previousHitTime = -1;
private double strainValueOf(DifficultyHitObject current)
{
if (previousHitTime == -1)
{
previousHitTime = current.StartTime;
return 0;
}
else
{
double objectStrain = 0.5;
objectStrain += speedBonus(current.StartTime - previousHitTime);
previousHitTime = current.StartTime;
return objectStrain;
}
}
public double StrainValueAt(DifficultyHitObject current)
{
return strainValueOf(current);
}
/// <summary>
/// Applies a speed bonus dependent on the time since the last hit performed using this key.
/// </summary>
/// <param name="notePairDuration">The duration between the current and previous note hit using the same key.</param>
private double speedBonus(double notePairDuration)
{
return 175 / Math.Pow(notePairDuration + 100, 1);
}
}
/// <summary>
/// Calculates the stamina coefficient of taiko difficulty.
/// </summary>
/// <remarks>
/// The reference play style chosen uses two hands, with full alternating (the hand changes after every hit).
/// </remarks>
public class Stamina : StrainDecaySkill
2020-05-11 05:50:02 +00:00
{
protected override double SkillMultiplier => 1;
protected override double StrainDecayBase => 0.4;
2022-05-10 08:17:40 +00:00
private SingleKeyStamina[] keyStamina = new SingleKeyStamina[4]
{
new SingleKeyStamina(),
new SingleKeyStamina(),
new SingleKeyStamina(),
new SingleKeyStamina()
};
2022-05-10 08:17:40 +00:00
private int donIndex = 1;
private int katIndex = 3;
2020-05-11 05:50:02 +00:00
/// <summary>
/// Creates a <see cref="Stamina"/> skill.
/// </summary>
/// <param name="mods">Mods for use in skill calculations.</param>
2022-05-10 08:17:40 +00:00
public Stamina(Mod[] mods)
: base(mods)
2020-05-11 05:50:02 +00:00
{
}
2022-05-10 08:17:40 +00:00
private SingleKeyStamina getNextSingleKeyStamina(TaikoDifficultyHitObject current)
2020-05-11 05:50:02 +00:00
{
2022-05-10 08:17:40 +00:00
if (current.HitType == HitType.Centre)
2020-06-08 07:30:26 +00:00
{
2022-05-10 08:17:40 +00:00
donIndex = donIndex == 0 ? 1 : 0;
return keyStamina[donIndex];
2020-06-08 07:30:26 +00:00
}
2022-05-10 08:17:40 +00:00
else
2020-05-11 05:50:02 +00:00
{
2022-05-10 08:17:40 +00:00
katIndex = katIndex == 2 ? 3 : 2;
return keyStamina[katIndex];
2020-05-11 05:50:02 +00:00
}
}
2022-05-10 08:17:40 +00:00
private double sigmoid(double val, double center, double width)
2020-05-11 05:50:02 +00:00
{
2022-05-10 08:17:40 +00:00
return Math.Tanh(Math.E * -(val - center) / width);
2020-08-22 15:51:35 +00:00
}
2022-05-10 08:17:40 +00:00
protected override double StrainValueOf(DifficultyHitObject current)
2020-08-22 15:51:35 +00:00
{
2022-05-10 08:17:40 +00:00
if (!(current.BaseObject is Hit))
{
return 0.0;
}
TaikoDifficultyHitObject hitObject = (TaikoDifficultyHitObject)current;
double objectStrain = getNextSingleKeyStamina(hitObject).StrainValueAt(hitObject);
2020-08-22 15:51:35 +00:00
2022-05-10 08:17:40 +00:00
return objectStrain;
2020-05-11 05:50:02 +00:00
}
}
}