From f6b13ca79dd271141ba6de8d18ec1fd1b69a599b Mon Sep 17 00:00:00 2001 From: smoogipoo Date: Sat, 16 Feb 2019 11:11:31 +0900 Subject: [PATCH] Rewrite catch diffcalc for readability + attempt to fix --- .../Preprocessing/CatchDifficultyHitObject.cs | 41 +++--------------- .../Difficulty/Skills/Movement.cs | 42 +++++++++++++------ 2 files changed, 36 insertions(+), 47 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs index 5dbd60d700..6ce45bbbde 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs @@ -6,63 +6,34 @@ using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Objects; -using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing { public class CatchDifficultyHitObject : DifficultyHitObject { private const float normalized_hitobject_radius = 41.0f; - private const float absolute_player_positioning_error = 16f; public new CatchHitObject BaseObject => (CatchHitObject)base.BaseObject; - public float MovementDistance { get; private set; } + public new CatchHitObject LastObject => (CatchHitObject)base.LastObject; + + public readonly float NormalizedPosition; + /// /// Milliseconds elapsed since the start time of the previous , with a minimum of 25ms. /// public readonly double StrainTime; - private readonly float scalingFactor; - - private readonly CatchHitObject lastObject; - public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, double timeRate, float halfCatcherWidth) : base(hitObject, lastObject, timeRate) { - this.lastObject = (CatchHitObject)lastObject; - // We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps. - scalingFactor = normalized_hitobject_radius / halfCatcherWidth; + var scalingFactor = normalized_hitobject_radius / halfCatcherWidth; - setDistances(); + NormalizedPosition = BaseObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; // Every strain interval is hard capped at the equivalent of 600 BPM streaming speed as a safety measure StrainTime = Math.Max(25, DeltaTime); } - - private void setDistances() - { - float lastPosition = getNormalizedPosition(lastObject); - float currentPosition = getNormalizedPosition(BaseObject); - - // After a hyperdash the player is assumed to be in the correct position - if (lastObject.LazyMovementDistance != null && !lastObject.HyperDash) - lastPosition += lastObject.LazyMovementDistance.Value; - - BaseObject.LazyMovementDistance = - MathHelper.Clamp( - lastPosition, - currentPosition - (normalized_hitobject_radius - absolute_player_positioning_error), - currentPosition + (normalized_hitobject_radius - absolute_player_positioning_error)) // Obtain new lazy position, but be stricter by allowing for an error of a certain degree of the player. - - currentPosition; // Subtract HitObject position to obtain offset - - MovementDistance = Math.Abs(currentPosition - lastPosition + BaseObject.LazyMovementDistance.Value); - - if (currentPosition < lastPosition) - MovementDistance *= -1; - } - - private float getNormalizedPosition(CatchHitObject hitObject) => hitObject.X * CatchPlayfield.BASE_WIDTH * scalingFactor; } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index 8137437959..e06ca08fbe 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs @@ -3,10 +3,10 @@ using System; using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; -using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; +using osuTK; namespace osu.Game.Rulesets.Catch.Difficulty.Skills { @@ -21,43 +21,61 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills protected override double DecayWeight => 0.94; + private float lastPlayerPosition; + private float lastDistanceMoved; + protected override double StrainValueOf(DifficultyHitObject current) { var catchCurrent = (CatchDifficultyHitObject)current; - var catchPrevious = Previous.Count > 0 ? (CatchDifficultyHitObject)Previous[0] : null; - var sqrtStrain = Math.Sqrt(catchCurrent.StrainTime); + float playerPosition = MathHelper.Clamp( + lastPlayerPosition, + catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error), + catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) + ); - double distanceAddition = Math.Pow(Math.Abs(catchCurrent.MovementDistance), 1.3) / 500; + float distanceMoved = playerPosition - lastPlayerPosition; + + double distanceAddition = Math.Pow(Math.Abs(distanceMoved), 1.3) / 500; + double sqrtStrain = Math.Sqrt(catchCurrent.StrainTime); double bonus = 0; - if (Math.Abs(catchCurrent.MovementDistance) > 0.1) + // Direction changes give an extra point! + if (Math.Abs(distanceMoved) > 0.1) { - if (catchPrevious != null && catchPrevious.MovementDistance > 0.1 && Math.Sign(catchCurrent.MovementDistance) != Math.Sign(catchPrevious.MovementDistance)) + if (Math.Abs(lastDistanceMoved) > 0.1 && Math.Sign(distanceMoved) != Math.Sign(lastDistanceMoved)) { - double bonusFactor = Math.Min(absolute_player_positioning_error, Math.Abs(catchCurrent.MovementDistance)) / absolute_player_positioning_error; + double bonusFactor = Math.Min(absolute_player_positioning_error, Math.Abs(distanceMoved)) / absolute_player_positioning_error; distanceAddition += direction_change_bonus / sqrtStrain * bonusFactor; // Bonus for tougher direction switches and "almost" hyperdashes at this point - if (catchPrevious.BaseObject.DistanceToHyperDash <= 10 / CatchPlayfield.BASE_WIDTH) + if (catchCurrent.LastObject.DistanceToHyperDash <= 10 / CatchPlayfield.BASE_WIDTH) bonus = 0.3 * bonusFactor; } // Base bonus for every movement, giving some weight to streams. - distanceAddition += 7.5 * Math.Min(Math.Abs(catchCurrent.MovementDistance), normalized_hitobject_radius * 2) / (normalized_hitobject_radius * 6) / sqrtStrain; + distanceAddition += 7.5 * Math.Min(Math.Abs(distanceMoved), normalized_hitobject_radius * 2) / (normalized_hitobject_radius * 6) / sqrtStrain; } // Bonus for "almost" hyperdashes at corner points - if (catchPrevious?.BaseObject is Fruit && catchPrevious.BaseObject.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) + if (catchCurrent.LastObject.DistanceToHyperDash <= 10.0f / CatchPlayfield.BASE_WIDTH) { - if (!catchPrevious.BaseObject.HyperDash) + if (!catchCurrent.LastObject.HyperDash) bonus += 1.0; + else + { + // After a hyperdash we ARE in the correct position. Always! + playerPosition = catchCurrent.NormalizedPosition; + } - distanceAddition *= 1.0 + bonus * ((10 - catchPrevious.BaseObject.DistanceToHyperDash * CatchPlayfield.BASE_WIDTH) / 10); + distanceAddition *= 1.0 + bonus * ((10 - catchCurrent.LastObject.DistanceToHyperDash * CatchPlayfield.BASE_WIDTH) / 10); } + lastPlayerPosition = playerPosition; + lastDistanceMoved = distanceMoved; + return distanceAddition / catchCurrent.StrainTime; } }