protected override double StrainValueOf(DifficultyHitObject current) { // drum rolls and swells are exempt. if (!(current.BaseObject is Hit)) { resetRhythmAndStrain(); return(0.0); } currentStrain *= strain_decay; TaikoDifficultyHitObject hitObject = (TaikoDifficultyHitObject)current; notesSinceRhythmChange += 1; // rhythm difficulty zero (due to rhythm not changing) => no rhythm strain. if (hitObject.Rhythm.Difficulty == 0.0) { return(0.0); } double objectStrain = hitObject.Rhythm.Difficulty; objectStrain *= repetitionPenalties(hitObject); objectStrain *= patternLengthPenalty(notesSinceRhythmChange); objectStrain *= speedPenalty(hitObject.DeltaTime); // careful - needs to be done here since calls above read this value notesSinceRhythmChange = 0; currentStrain += objectStrain; return(currentStrain); }
protected override double StrainValueOf(DifficultyHitObject current) { if (!(current.BaseObject is Hit)) { return(0.0); } TaikoDifficultyHitObject hitObject = (TaikoDifficultyHitObject)current; if (hitObject.ObjectIndex % 2 == hand) { double objectStrain = 1; if (hitObject.ObjectIndex == 1) { return(1); } notePairDurationHistory.Enqueue(hitObject.DeltaTime + offhandObjectDuration); double shortestRecentNote = notePairDurationHistory.Min(); objectStrain += speedBonus(shortestRecentNote); if (hitObject.StaminaCheese) { objectStrain *= cheesePenalty(hitObject.DeltaTime + offhandObjectDuration); } return(objectStrain); } offhandObjectDuration = hitObject.DeltaTime; return(0); }
protected override double StrainValueOf(DifficultyHitObject current) { if (!(current.BaseObject is Hit)) { return(0.0); } TaikoDifficultyHitObject hitObject = (TaikoDifficultyHitObject)current; return(getNextSingleKeyStamina(hitObject).StrainValueOf(hitObject)); }
/// <summary> /// Get the next <see cref="SingleKeyStamina"/> to use for the given <see cref="TaikoDifficultyHitObject"/>. /// </summary> /// <param name="current">The current <see cref="TaikoDifficultyHitObject"/>.</param> private SingleKeyStamina getNextSingleKeyStamina(TaikoDifficultyHitObject current) { // Alternate key for the same color. if (current.HitType == HitType.Centre) { centreKeyIndex = (centreKeyIndex + 1) % 2; return(centreKeyStamina[centreKeyIndex]); } rimKeyIndex = (rimKeyIndex + 1) % 2; return(rimKeyStamina[rimKeyIndex]); }
/// <summary> /// Returns a penalty to apply to the current hit object caused by repeating rhythm changes. /// </summary> /// <remarks> /// Repetitions of more recent patterns are associated with a higher penalty. /// </remarks> /// <param name="hitObject">The current hit object being considered.</param> private double repetitionPenalties(TaikoDifficultyHitObject hitObject) { double penalty = 1; rhythmHistory.Enqueue(hitObject); for (int mostRecentPatternsToCompare = 2; mostRecentPatternsToCompare <= rhythm_history_max_length / 2; mostRecentPatternsToCompare++) { for (int start = rhythmHistory.Count - mostRecentPatternsToCompare - 1; start >= 0; start--) { if (!samePattern(start, mostRecentPatternsToCompare)) { continue; } int notesSince = hitObject.ObjectIndex - rhythmHistory[start].ObjectIndex; penalty *= repetitionPenalty(notesSince); break; } } return(penalty); }