From 3ba5dce052224276e96ca5de1cc8c731e0f434ff Mon Sep 17 00:00:00 2001 From: Shawdooow Date: Sun, 31 Dec 2017 11:15:14 -0500 Subject: [PATCH] new Approach to approach rate --- .../Beatmaps/OsuBeatmapProcessor.cs | 5 ++++- osu.Game.Rulesets.Osu/Mods/OsuMod.cs | 8 +++----- .../Drawables/Connections/FollowPointRenderer.cs | 8 ++++---- .../Objects/Drawables/DrawableHitCircle.cs | 6 +++--- .../Objects/Drawables/DrawableOsuHitObject.cs | 13 ++++++------- .../Objects/Drawables/DrawableSpinner.cs | 4 ++-- .../Objects/Drawables/Pieces/SliderBody.cs | 2 +- osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs | 10 ++++++++++ osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs | 15 ++++++++------- 9 files changed, 41 insertions(+), 30 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs index 31b374f71d..e8742d24a6 100644 --- a/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs +++ b/osu.Game.Rulesets.Osu/Beatmaps/OsuBeatmapProcessor.cs @@ -37,7 +37,6 @@ namespace osu.Game.Rulesets.Osu.Beatmaps private void applyStacking(Beatmap beatmap) { const int stack_distance = 3; - float stackThreshold = DrawableOsuHitObject.TIME_PREEMPT * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; // Reset stacking for (int i = 0; i <= beatmap.HitObjects.Count - 1; i++) @@ -58,6 +57,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps continue; double endTime = (stackBaseObject as IHasEndTime)?.EndTime ?? stackBaseObject.StartTime; + float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; if (objectN.StartTime - endTime > stackThreshold) //We are no longer within stacking range of the next object. @@ -112,6 +112,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps if (objectN is Spinner) continue; double endTime = (objectN as IHasEndTime)?.EndTime ?? objectN.StartTime; + float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; if (objectI.StartTime - endTime > stackThreshold) //We are no longer within stacking range of the previous object. @@ -165,6 +166,8 @@ namespace osu.Game.Rulesets.Osu.Beatmaps OsuHitObject objectN = beatmap.HitObjects[n]; if (objectN is Spinner) continue; + float stackThreshold = objectN.TimePreempt * beatmap.BeatmapInfo?.StackLeniency ?? 0.7f; + if (objectI.StartTime - objectN.StartTime > stackThreshold) //We are no longer within stacking range of the previous object. break; diff --git a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs index 7b1f80f439..dd01ef9af7 100644 --- a/osu.Game.Rulesets.Osu/Mods/OsuMod.cs +++ b/osu.Game.Rulesets.Osu/Mods/OsuMod.cs @@ -36,14 +36,12 @@ namespace osu.Game.Rulesets.Osu.Mods private const double fade_in_duration_multiplier = 0.4; private const double fade_out_duration_multiplier = 0.3; - private float preEmpt => DrawableOsuHitObject.TIME_PREEMPT; - public void ApplyToDrawableHitObjects(IEnumerable drawables) { foreach (var d in drawables.OfType()) { d.ApplyCustomUpdateState += ApplyHiddenState; - d.FadeInDuration = preEmpt * fade_in_duration_multiplier; + d.FadeInDuration = d.HitObject.TimePreempt * fade_in_duration_multiplier; } } @@ -52,8 +50,8 @@ namespace osu.Game.Rulesets.Osu.Mods if (!(drawable is DrawableOsuHitObject d)) return; - var fadeOutStartTime = d.HitObject.StartTime - preEmpt + d.FadeInDuration; - var fadeOutDuration = preEmpt * fade_out_duration_multiplier; + var fadeOutStartTime = d.HitObject.StartTime - d.HitObject.TimePreempt + d.FadeInDuration; + var fadeOutDuration = d.HitObject.TimePreempt * fade_out_duration_multiplier; // new duration from completed fade in to end (before fading out) var longFadeDuration = ((d.HitObject as IHasEndTime)?.EndTime ?? d.HitObject.StartTime) - fadeOutStartTime; diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs index fca9187047..60ee10193f 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Connections/FollowPointRenderer.cs @@ -96,12 +96,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections using (fp.BeginAbsoluteSequence(fadeInTime)) { - fp.FadeIn(DrawableOsuHitObject.TIME_FADEIN); - fp.ScaleTo(1, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); + fp.FadeIn(currHitObject.TimeFadein); + fp.ScaleTo(1, currHitObject.TimeFadein, Easing.Out); - fp.MoveTo(pointEndPosition, DrawableOsuHitObject.TIME_FADEIN, Easing.Out); + fp.MoveTo(pointEndPosition, currHitObject.TimeFadein, Easing.Out); - fp.Delay(fadeOutTime - fadeInTime).FadeOut(DrawableOsuHitObject.TIME_FADEIN); + fp.Delay(fadeOutTime - fadeInTime).FadeOut(currHitObject.TimeFadein); } fp.Expire(true); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs index 6220bbd120..bb405ea7fd 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableHitCircle.cs @@ -88,8 +88,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { base.UpdatePreemptState(); - ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, TIME_PREEMPT)); - ApproachCircle.ScaleTo(1.1f, TIME_PREEMPT); + ApproachCircle.FadeIn(Math.Min(FadeInDuration * 2, HitObject.TimePreempt)); + ApproachCircle.ScaleTo(1.1f, HitObject.TimePreempt); } protected override void UpdateCurrentState(ArmedState state) @@ -99,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables switch (state) { case ArmedState.Idle: - this.Delay(TIME_PREEMPT).FadeOut(500); + this.Delay(HitObject.TimePreempt).FadeOut(500); Expire(true); diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs index f5f0300ae1..1a8ec68df2 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableOsuHitObject.cs @@ -10,26 +10,25 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { public class DrawableOsuHitObject : DrawableHitObject { - public const float TIME_PREEMPT = 600; - public const float TIME_FADEIN = 400; - /// /// The number of milliseconds used to fade in. /// - public virtual double FadeInDuration { get; set; } = TIME_FADEIN; + public virtual double FadeInDuration { get; set; } - public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - TIME_PREEMPT; + public override bool IsPresent => base.IsPresent || State.Value == ArmedState.Idle && Time.Current >= HitObject.StartTime - HitObject.TimePreempt; protected DrawableOsuHitObject(OsuHitObject hitObject) : base(hitObject) { + FadeInDuration = hitObject.TimeFadein; + AccentColour = HitObject.ComboColour; Alpha = 0; } protected sealed override void UpdateState(ArmedState state) { - double transformTime = HitObject.StartTime - TIME_PREEMPT; + double transformTime = HitObject.StartTime - HitObject.TimePreempt; base.ApplyTransformsAt(transformTime, true); base.ClearTransformsAfter(transformTime, true); @@ -38,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables { UpdatePreemptState(); - using (BeginDelayedSequence(TIME_PREEMPT + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true)) + using (BeginDelayedSequence(HitObject.TimePreempt + (Judgements.FirstOrDefault()?.TimeOffset ?? 0), true)) UpdateCurrentState(state); } } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs index 5351ad50c4..e471ad4e9b 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/DrawableSpinner.cs @@ -191,14 +191,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables base.UpdatePreemptState(); circleContainer.ScaleTo(spinner.Scale * 0.3f); - circleContainer.ScaleTo(spinner.Scale, TIME_PREEMPT / 1.4f, Easing.OutQuint); + circleContainer.ScaleTo(spinner.Scale, HitObject.TimePreempt / 1.4f, Easing.OutQuint); Disc.RotateTo(-720); symbol.RotateTo(-720); mainContainer .ScaleTo(0) - .ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, TIME_PREEMPT - 150, Easing.OutQuint) + .ScaleTo(spinner.Scale * circle.DrawHeight / DrawHeight * 1.4f, HitObject.TimePreempt - 150, Easing.OutQuint) .Then() .ScaleTo(1, 500, Easing.OutQuint); } diff --git a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs index 75c2c15084..4914ec07c0 100644 --- a/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs +++ b/osu.Game.Rulesets.Osu/Objects/Drawables/Pieces/SliderBody.cs @@ -167,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces public void UpdateProgress(double progress, int repeat) { double start = 0; - double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - DrawableOsuHitObject.TIME_PREEMPT)) / DrawableOsuHitObject.TIME_FADEIN, 0, 1) : 1; + double end = snakingIn ? MathHelper.Clamp((Time.Current - (slider.StartTime - slider.TimePreempt)) / slider.TimeFadein, 0, 1) : 1; if (repeat >= slider.RepeatCount - 1) { diff --git a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs index a3a6527b31..0a96d6367a 100644 --- a/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs +++ b/osu.Game.Rulesets.Osu/Objects/OsuHitObject.cs @@ -20,6 +20,9 @@ namespace osu.Game.Rulesets.Osu.Objects private const double hit_window_100 = 80; private const double hit_window_300 = 30; + public float TimePreempt = 600; + public float TimeFadein = 400; + public Vector2 Position { get; set; } public float X => Position.X; public float Y => Position.Y; @@ -72,6 +75,13 @@ namespace osu.Game.Rulesets.Osu.Objects { base.ApplyDefaultsToSelf(controlPointInfo, difficulty); + if (difficulty.ApproachRate >= 5) + TimePreempt = 1200 - (difficulty.ApproachRate - 5) * 150; + else + TimePreempt = 1800 - difficulty.ApproachRate * 120; + TimeFadein = TimePreempt / 3; + + Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2; } } diff --git a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs index ba774e887f..a4c345f96c 100644 --- a/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs +++ b/osu.Game.Rulesets.Osu/Replays/OsuAutoGenerator.cs @@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables; using System; using System.Diagnostics; using osu.Framework.Graphics; +using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Scoring; @@ -133,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Replays // Do some nice easing for cursor movements if (Frames.Count > 0) { - moveToHitObject(h.StartTime, startPosition, h.Radius, easing); + moveToHitObject(h, startPosition, easing); } // Add frames to click the hitobject @@ -191,12 +192,12 @@ namespace osu.Game.Rulesets.Osu.Replays } } - private void moveToHitObject(double targetTime, Vector2 targetPos, double hitObjectRadius, Easing easing) + private void moveToHitObject(OsuHitObject h, Vector2 targetPos, Easing easing) { ReplayFrame lastFrame = Frames[Frames.Count - 1]; // Wait until Auto could "see and react" to the next note. - double waitTime = targetTime - Math.Max(0.0, DrawableOsuHitObject.TIME_PREEMPT - reactionTime); + double waitTime = h.StartTime - Math.Max(0.0, h.TimePreempt - reactionTime); if (waitTime > lastFrame.Time) { lastFrame = new ReplayFrame(waitTime, lastFrame.MouseX, lastFrame.MouseY, lastFrame.ButtonState); @@ -205,17 +206,17 @@ namespace osu.Game.Rulesets.Osu.Replays Vector2 lastPosition = lastFrame.Position; - double timeDifference = ApplyModsToTime(targetTime - lastFrame.Time); + double timeDifference = ApplyModsToTime(h.StartTime - lastFrame.Time); // Only "snap" to hitcircles if they are far enough apart. As the time between hitcircles gets shorter the snapping threshold goes up. if (timeDifference > 0 && // Sanity checks - ((lastPosition - targetPos).Length > hitObjectRadius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough + ((lastPosition - targetPos).Length > h.Radius * (1.5 + 100.0 / timeDifference) || // Either the distance is big enough timeDifference >= 266)) // ... or the beats are slow enough to tap anyway. { // Perform eased movement - for (double time = lastFrame.Time + FrameDelay; time < targetTime; time += FrameDelay) + for (double time = lastFrame.Time + FrameDelay; time < h.StartTime; time += FrameDelay) { - Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPos, lastFrame.Time, targetTime, easing); + Vector2 currentPosition = Interpolation.ValueAt(time, lastPosition, targetPos, lastFrame.Time, h.StartTime, easing); AddFrameToReplay(new ReplayFrame((int)time, currentPosition.X, currentPosition.Y, lastFrame.ButtonState)); }