mirror of
https://github.com/ppy/osu
synced 2024-12-13 10:28:17 +00:00
96 lines
3.2 KiB
C#
96 lines
3.2 KiB
C#
// 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;
|
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
|
using osu.Game.Rulesets.Difficulty.Skills;
|
|
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing;
|
|
using osu.Game.Rulesets.Taiko.Objects;
|
|
|
|
namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
|
|
{
|
|
public class Strain : Skill
|
|
{
|
|
private const double rhythm_change_base_threshold = 0.2;
|
|
private const double rhythm_change_base = 2.0;
|
|
|
|
protected override double SkillMultiplier => 1;
|
|
protected override double StrainDecayBase => 0.3;
|
|
|
|
private ColourSwitch lastColourSwitch = ColourSwitch.None;
|
|
|
|
private int sameColourCount = 1;
|
|
|
|
protected override double StrainValueOf(DifficultyHitObject current)
|
|
{
|
|
double addition = 1;
|
|
|
|
// 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;
|
|
|
|
if (hasRhythmChange(current))
|
|
addition += 1;
|
|
}
|
|
else
|
|
{
|
|
lastColourSwitch = ColourSwitch.None;
|
|
sameColourCount = 1;
|
|
}
|
|
|
|
double additionFactor = 1;
|
|
|
|
// Scale the addition factor linearly from 0.4 to 1 for DeltaTime from 0 to 50
|
|
if (current.DeltaTime < 50)
|
|
additionFactor = 0.4 + 0.6 * current.DeltaTime / 50;
|
|
|
|
return additionFactor * addition;
|
|
}
|
|
|
|
private bool hasRhythmChange(DifficultyHitObject current)
|
|
{
|
|
// We don't want a division by zero if some random mapper decides to put two HitObjects at the same time.
|
|
if (current.DeltaTime == 0 || Previous.Count == 0 || Previous[0].DeltaTime == 0)
|
|
return false;
|
|
|
|
double timeElapsedRatio = Math.Max(Previous[0].DeltaTime / current.DeltaTime, current.DeltaTime / Previous[0].DeltaTime);
|
|
|
|
if (timeElapsedRatio >= 8)
|
|
return false;
|
|
|
|
double difference = Math.Log(timeElapsedRatio, rhythm_change_base) % 1.0;
|
|
|
|
return difference > rhythm_change_base_threshold && difference < 1 - rhythm_change_base_threshold;
|
|
}
|
|
|
|
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
|
|
}
|
|
}
|
|
}
|