internal void CalculateStrains(DifficultyHitObjectTaiko PreviousHitObject, double TimeRate) { // Rather simple, but more specialized things are inherently inaccurate due to the big difference playstyles and opinions make. // See Taiko feedback thread. TimeElapsed = (double)(BaseHitObject.StartTime - PreviousHitObject.BaseHitObject.StartTime) / TimeRate; double Decay = Math.Pow(DECAY_BASE, TimeElapsed / 1000); double Addition = 1; // Only if we are no slider or spinner we get an extra addition if (PreviousHitObject.BaseHitObject.IsType(HitObjectType.Normal) && BaseHitObject.IsType(HitObjectType.Normal) && BaseHitObject.StartTime - PreviousHitObject.BaseHitObject.StartTime < 1000) // And we only want to check out hitobjects which aren't so far in the past { Addition += ColorChangeAddition(PreviousHitObject); Addition += RhythmChangeAddition(PreviousHitObject); } double AdditionFactor = 1.0; // Scale AdditionFactor linearly from 0.4 to 1 for TimeElapsed from 0 to 50 if (TimeElapsed < 50.0) { AdditionFactor = 0.4 + 0.6 * TimeElapsed / 50.0; } Strain = PreviousHitObject.Strain * Decay + Addition * AdditionFactor; }
internal double ColorChangeAddition(DifficultyHitObjectTaiko PreviousHitObject) { // If we don't have the same color, trigger a color change! if (PreviousHitObject.IsBlue != IsBlue) { LastColorSwitchEven = PreviousHitObject.SameColorSince % 2 == 0 ? ColorSwitch.Even : ColorSwitch.Odd; // We only want a bonus if the parity of the color switch changes! switch (PreviousHitObject.LastColorSwitchEven) { case ColorSwitch.Even: if (LastColorSwitchEven == ColorSwitch.Odd) { return(COLOR_CHANGE_BONUS); } break; case ColorSwitch.Odd: if (LastColorSwitchEven == ColorSwitch.Even) { return(COLOR_CHANGE_BONUS); } break; } } // No color change? Increment counter and keep track of last color switch else { LastColorSwitchEven = PreviousHitObject.LastColorSwitchEven; SameColorSince = PreviousHitObject.SameColorSince + 1; } return(0); }
internal double RhythmChangeAddition(DifficultyHitObjectTaiko PreviousHitObject) { // We don't want a division by zero if some random mapper decides to put 2 HitObjects at the same time. if (TimeElapsed == 0 || PreviousHitObject.TimeElapsed == 0) { return(0); } double TimeElapsedRatio = Math.Max((double)PreviousHitObject.TimeElapsed / (double)TimeElapsed, (double)TimeElapsed / (double)PreviousHitObject.TimeElapsed); if (TimeElapsedRatio >= 8) { return(0); } double Difference = Math.Log(TimeElapsedRatio, RHYTHM_CHANGE_BASE) % 1.0; if (Difference > RHYTHM_CHANGE_BASE_THRESHOLD && Difference < 1 - RHYTHM_CHANGE_BASE_THRESHOLD) { return(RHYTHM_CHANGE_BONUS); } return(0); }