diff --git a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs index f12c41a415..26ad6c2891 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/CatchDifficultyCalculator.cs @@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { - CatchHitObject? lastObject = null; + CatchHitObject? lastObject0 = null, lastObject1 = null; List objects = new List(); @@ -63,10 +63,11 @@ namespace osu.Game.Rulesets.Catch.Difficulty if (hitObject is Banana || hitObject is TinyDroplet) continue; - if (lastObject != null) - objects.Add(new CatchDifficultyHitObject(hitObject, lastObject, clockRate, halfCatcherWidth, objects, objects.Count)); + if (lastObject0 != null) + objects.Add(new CatchDifficultyHitObject(hitObject, lastObject0, lastObject1, clockRate, halfCatcherWidth, objects, objects.Count)); - lastObject = hitObject; + lastObject1 = lastObject0; + lastObject0 = hitObject; } return objects; diff --git a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs index 3bcfce3a56..4f85a3af1e 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Objects; @@ -18,21 +19,31 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing public new PalpableCatchHitObject LastObject => (PalpableCatchHitObject)base.LastObject; public readonly float NormalizedPosition; - public readonly float LastNormalizedPosition; + public readonly float NormalizedPositionLast0; + public readonly float? NormalizedPositionLast1 = null; /// /// Milliseconds elapsed since the start time of the previous , with a minimum of 40ms. /// public readonly double StrainTime; - public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, float halfCatcherWidth, List objects, int index) - : base(hitObject, lastObject, clockRate, objects, index) + private PalpableCatchHitObject lastObj0; + private PalpableCatchHitObject? lastObj1; + + public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject0, HitObject? lastObject1, double clockRate, float halfCatcherWidth, List objects, int index) + : base(hitObject, lastObject0, clockRate, objects, index) { // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. float scalingFactor = normalized_hitobject_radius / halfCatcherWidth; + lastObj0 = (PalpableCatchHitObject)lastObject0; + lastObj1 = (PalpableCatchHitObject?)lastObject1; + NormalizedPosition = BaseObject.EffectiveX * scalingFactor; - LastNormalizedPosition = LastObject.EffectiveX * scalingFactor; + NormalizedPositionLast0 = lastObj0.EffectiveX * scalingFactor; + + if (lastObj1.IsNotNull()) + NormalizedPositionLast1 = lastObj1.EffectiveX * scalingFactor; // Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure StrainTime = Math.Max(40, DeltaTime); diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index cfb3fe40be..8b9575334a 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using osu.Framework.Extensions.ObjectExtensions; using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; @@ -49,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills { var catchCurrent = (CatchDifficultyHitObject)current; - lastPlayerPosition ??= catchCurrent.LastNormalizedPosition; + lastPlayerPosition ??= catchCurrent.NormalizedPositionLast0; float playerPosition = Math.Clamp( lastPlayerPosition.Value, @@ -59,6 +60,23 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills float distanceMoved = playerPosition - lastPlayerPosition.Value; + if (catchCurrent.NormalizedPositionLast0.IsNotNull() && catchCurrent.NormalizedPositionLast1.IsNotNull()) + { + float lenience = normalized_hitobject_radius * 2; + float antiCheese = 1; + + float deltaCurrLast0 = Math.Clamp(lenience - Math.Abs(catchCurrent.NormalizedPosition - catchCurrent.NormalizedPositionLast0), 0, absolute_player_positioning_error); + antiCheese *= deltaCurrLast0 / absolute_player_positioning_error; + + float deltaCurrLast1 = Math.Clamp(lenience - Math.Abs((float)(catchCurrent.NormalizedPosition - catchCurrent.NormalizedPositionLast1)), 0, absolute_player_positioning_error); + antiCheese *= deltaCurrLast1 / absolute_player_positioning_error; + + float deltaLast0Last1 = Math.Clamp(lenience - Math.Abs((float)(catchCurrent.NormalizedPositionLast0 - catchCurrent.NormalizedPositionLast1)), 0, absolute_player_positioning_error); + antiCheese *= deltaLast0Last1 / absolute_player_positioning_error; + + distanceMoved *= 1 - antiCheese; + } + double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catcherSpeedMultiplier); double distanceAddition = (Math.Pow(Math.Abs(distanceMoved), 1.3) / 510);