From 323e4ac26b8172865bc6fbede9c39fb05ee5da40 Mon Sep 17 00:00:00 2001 From: Samuel Cattini-Schultz Date: Sun, 21 Feb 2021 18:24:27 +1100 Subject: [PATCH] Refactor catch Movement skill to not require explicit clockrate usage In catch, rate adjustment mods do not only affect the timings of hitobjects, but also the speed of the player's catcher. This catcher speed change has an impact on difficulty which is currently accounted for by using the clockrate directly in calculations. Semantically this is a bad idea because clockrate adjustments are supposed to be fully accounted for in DifficultyHitObjects, but passing clockrate here for the purpose of being used as catcher speed doesn't make much sense, especially since it is copied in every DifficultyHitObject despite being the same value. It makes more sense to account for this catch specific impact by handling rate adjustment mods in a catch specific way, or more specifically in a Movement skill specific way. --- .../Preprocessing/CatchDifficultyHitObject.cs | 3 --- .../Difficulty/Skills/Movement.cs | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs index d936ef97ac..e19098c580 100644 --- a/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs +++ b/osu.Game.Rulesets.Catch/Difficulty/Preprocessing/CatchDifficultyHitObject.cs @@ -24,8 +24,6 @@ public class CatchDifficultyHitObject : DifficultyHitObject /// public readonly double StrainTime; - public readonly double ClockRate; - public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, float halfCatcherWidth) : base(hitObject, lastObject, clockRate) { @@ -37,7 +35,6 @@ public CatchDifficultyHitObject(HitObject hitObject, HitObject lastObject, doubl // Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure StrainTime = Math.Max(40, DeltaTime); - ClockRate = clockRate; } } } diff --git a/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs b/osu.Game.Rulesets.Catch/Difficulty/Skills/Movement.cs index 9ad719be1a..7d61be7bb1 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 System.Linq; using osu.Game.Rulesets.Catch.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; @@ -26,10 +27,20 @@ public class Movement : Skill private float lastDistanceMoved; private double lastStrainTime; + /// + /// The speed multiplier applied to the player's catcher. + /// + private readonly double catcherSpeedMultiplier; + public Movement(Mod[] mods, float halfCatcherWidth) : base(mods) { HalfCatcherWidth = halfCatcherWidth; + + // In catch, rate adjustment mods do not only affect the timings of hitobjects, + // but also the speed of the player's catcher, which has an impact on difficulty + var rateAdjustMod = mods.FirstOrDefault(m => m is ModRateAdjust); + catcherSpeedMultiplier = (rateAdjustMod as ModRateAdjust)?.SpeedChange.Value ?? 1; } protected override double StrainValueOf(DifficultyHitObject current) @@ -46,7 +57,7 @@ protected override double StrainValueOf(DifficultyHitObject current) float distanceMoved = playerPosition - lastPlayerPosition.Value; - double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catchCurrent.ClockRate); + double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catcherSpeedMultiplier); double distanceAddition = (Math.Pow(Math.Abs(distanceMoved), 1.3) / 510); double sqrtStrain = Math.Sqrt(weightedStrainTime); @@ -79,7 +90,7 @@ protected override double StrainValueOf(DifficultyHitObject current) playerPosition = catchCurrent.NormalizedPosition; } - distanceAddition *= 1.0 + edgeDashBonus * ((20 - catchCurrent.LastObject.DistanceToHyperDash) / 20) * Math.Pow((Math.Min(catchCurrent.StrainTime * catchCurrent.ClockRate, 265) / 265), 1.5); // Edge Dashes are easier at lower ms values + distanceAddition *= 1.0 + edgeDashBonus * ((20 - catchCurrent.LastObject.DistanceToHyperDash) / 20) * Math.Pow((Math.Min(catchCurrent.StrainTime * catcherSpeedMultiplier, 265) / 265), 1.5); // Edge Dashes are easier at lower ms values } lastPlayerPosition = playerPosition;