public TpHitObject(HitObject baseHitObject, double radius) { BaseHitObject = baseHitObject; var scalingFactor = 52 / (float)radius; if (radius < CIRCLESIZE_BUFF_TRESHOLD) //CS ~5.5 -> ~6.5, up to 10% increase { scalingFactor *= (float)Math.Min(1.1, (50 + CIRCLESIZE_BUFF_TRESHOLD - radius) / 50); } _normalizedStartPosition = baseHitObject.StartPosition * scalingFactor; if (baseHitObject.IsHitObjectType(HitObjectType.Slider)) { var slider = (Slider)baseHitObject; while (slider.Curve == null) { } var sliderFollowCircleRadius = (float)radius * 3; var segmentLength = Math.Min(slider.Duration / slider.SegmentCount, 60000); var segmentEndTime = slider.StartTime + segmentLength; var cursorPos = slider.StartPosition; for (var time = slider.StartTime + LAZY_SLIDER_STEP_LENGTH; time < segmentEndTime; time += LAZY_SLIDER_STEP_LENGTH) { var difference = slider.PositionAtTime(time) - cursorPos; var distance = difference.Length; if (distance <= sliderFollowCircleRadius) { continue; } difference = difference.Normalize(); distance -= sliderFollowCircleRadius; cursorPos += difference * distance; _lazySliderLengthFirst += distance; } _lazySliderLengthFirst *= scalingFactor; if (slider.SegmentCount % 2 == 1) { _normalizedEndPosition = cursorPos * scalingFactor; } if (slider.SegmentCount <= 1) { return; } segmentEndTime += segmentLength; for (var time = segmentEndTime - segmentLength + LAZY_SLIDER_STEP_LENGTH; time < segmentEndTime; time += LAZY_SLIDER_STEP_LENGTH) { var difference = slider.PositionAtTime((int)time) - cursorPos; var distance = difference.Length; if (distance <= sliderFollowCircleRadius) { continue; } difference.Normalize(); distance -= sliderFollowCircleRadius; cursorPos += difference * distance; _lazySliderLengthSubsequent += distance; } if (slider.SegmentCount % 2 != 0) { return; } _normalizedEndPosition = cursorPos * scalingFactor; } else { _normalizedEndPosition = _normalizedStartPosition; } }