2020-05-11 13:50:02 +08: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.
|
|
|
|
|
|
|
|
|
|
using System.Collections.Generic;
|
2020-06-08 15:30:26 +08:00
|
|
|
|
using System.Linq;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
|
|
|
|
using osu.Game.Rulesets.Difficulty.Skills;
|
|
|
|
|
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
|
2020-06-08 15:30:26 +08:00
|
|
|
|
using osu.Game.Rulesets.Taiko.Objects;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
|
|
|
|
namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
|
|
|
|
|
{
|
|
|
|
|
public class Stamina : Skill
|
|
|
|
|
{
|
2020-06-08 15:30:26 +08:00
|
|
|
|
private readonly int hand;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
|
|
|
|
protected override double SkillMultiplier => 1;
|
|
|
|
|
protected override double StrainDecayBase => 0.4;
|
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
private const int max_history_length = 2;
|
|
|
|
|
private readonly List<double> notePairDurationHistory = new List<double>();
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
|
|
|
|
private double offhandObjectDuration = double.MaxValue;
|
|
|
|
|
|
|
|
|
|
// Penalty for tl tap or roll
|
2020-06-08 15:30:26 +08:00
|
|
|
|
private double cheesePenalty(double notePairDuration)
|
2020-05-11 13:50:02 +08:00
|
|
|
|
{
|
2020-06-08 15:30:26 +08:00
|
|
|
|
if (notePairDuration > 125) return 1;
|
|
|
|
|
if (notePairDuration < 100) return 0.6;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
return 0.6 + (notePairDuration - 100) * 0.016;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
private double speedBonus(double notePairDuration)
|
2020-05-11 13:50:02 +08:00
|
|
|
|
{
|
2020-06-08 15:30:26 +08:00
|
|
|
|
if (notePairDuration >= 200) return 0;
|
|
|
|
|
|
|
|
|
|
double bonus = 200 - notePairDuration;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
bonus *= bonus;
|
|
|
|
|
return bonus / 100000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override double StrainValueOf(DifficultyHitObject current)
|
|
|
|
|
{
|
2020-06-08 15:30:26 +08:00
|
|
|
|
if (!(current.BaseObject is Hit))
|
|
|
|
|
{
|
|
|
|
|
return 0.0;
|
|
|
|
|
}
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
TaikoDifficultyHitObject hitObject = (TaikoDifficultyHitObject)current;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
if (hitObject.N % 2 == hand)
|
2020-05-11 13:50:02 +08:00
|
|
|
|
{
|
2020-06-08 15:30:26 +08:00
|
|
|
|
double objectStrain = 1;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
if (hitObject.N == 1)
|
2020-05-11 13:50:02 +08:00
|
|
|
|
return 1;
|
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
notePairDurationHistory.Add(hitObject.NoteLength + offhandObjectDuration);
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
if (notePairDurationHistory.Count > max_history_length)
|
|
|
|
|
notePairDurationHistory.RemoveAt(0);
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
double shortestRecentNote = notePairDurationHistory.Min();
|
|
|
|
|
objectStrain += speedBonus(shortestRecentNote);
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
if (hitObject.StaminaCheese)
|
|
|
|
|
objectStrain *= cheesePenalty(hitObject.NoteLength + offhandObjectDuration);
|
2020-05-11 13:50:02 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
return objectStrain;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
}
|
2020-05-11 13:53:42 +08:00
|
|
|
|
|
2020-06-08 15:30:26 +08:00
|
|
|
|
offhandObjectDuration = hitObject.NoteLength;
|
|
|
|
|
return 0;
|
2020-05-11 13:50:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Stamina(bool rightHand)
|
|
|
|
|
{
|
|
|
|
|
hand = 0;
|
2020-05-11 13:53:42 +08:00
|
|
|
|
|
2020-05-11 13:50:02 +08:00
|
|
|
|
if (rightHand)
|
|
|
|
|
{
|
|
|
|
|
hand = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|