Add flags to return to classic slider scoring

This commit is contained in:
smoogipoo 2021-02-03 22:12:20 +09:00
parent 623b47f9af
commit 03b7817887
5 changed files with 66 additions and 4 deletions

View File

@ -123,7 +123,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
return;
}
var result = HitObject.HitWindows.ResultFor(timeOffset);
var result = ResultFor(timeOffset);
if (result == HitResult.None || CheckHittable?.Invoke(this, Time.Current) == false)
{
@ -146,6 +146,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
});
}
/// <summary>
/// Retrieves the <see cref="HitResult"/> for a time offset.
/// </summary>
/// <param name="timeOffset">The time offset.</param>
/// <returns>The hit result, or <see cref="HitResult.None"/> if <paramref name="timeOffset"/> doesn't result in a judgement.</returns>
protected virtual HitResult ResultFor(double timeOffset) => HitObject.HitWindows.ResultFor(timeOffset);
protected override void UpdateInitialTransforms()
{
base.UpdateInitialTransforms();

View File

@ -15,6 +15,7 @@ using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Skinning;
using osu.Game.Rulesets.Osu.Skinning.Default;
using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.Scoring;
using osuTK.Graphics;
using osu.Game.Skinning;
@ -249,7 +250,28 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (userTriggered || Time.Current < HitObject.EndTime)
return;
ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
if (HitObject.IgnoreJudgement)
{
ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
return;
}
// If not ignoring judgement, score proportionally based on the number of ticks hit, counting the head circle as a tick.
ApplyResult(r =>
{
int totalTicks = NestedHitObjects.Count;
int hitTicks = NestedHitObjects.Count(h => h.IsHit);
double hitFraction = (double)totalTicks / hitTicks;
if (hitTicks == totalTicks)
r.Type = HitResult.Great;
else if (hitFraction >= 0.5)
r.Type = HitResult.Ok;
else if (hitFraction > 0)
r.Type = HitResult.Meh;
else
r.Type = HitResult.Miss;
});
}
public override void PlaySamples()

View File

@ -7,6 +7,7 @@ using JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@ -19,6 +20,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected DrawableSlider DrawableSlider => (DrawableSlider)ParentHitObject;
public override bool DisplayResult => HitObject?.JudgeAsNormalHitCircle ?? base.DisplayResult;
private readonly IBindable<int> pathVersion = new Bindable<int>();
protected override OsuSkinComponents CirclePieceComponent => OsuSkinComponents.SliderHeadHitCircle;
@ -73,6 +76,18 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}
}
protected override HitResult ResultFor(double timeOffset)
{
Debug.Assert(HitObject != null);
if (HitObject.JudgeAsNormalHitCircle)
return base.ResultFor(timeOffset);
// If not judged as a normal hitcircle, only track whether a hit has occurred (via IgnoreHit) rather than a scorable hit result.
var result = base.ResultFor(timeOffset);
return result.IsHit() ? HitResult.IgnoreHit : result;
}
public Action<double> OnShake;
public override void Shake(double maximumLength) => OnShake?.Invoke(maximumLength);

View File

@ -114,6 +114,12 @@ namespace osu.Game.Rulesets.Osu.Objects
/// </summary>
public double TickDistanceMultiplier = 1;
/// <summary>
/// Whether this <see cref="Slider"/>'s judgement should be ignored.
/// If <c>false</c>, this <see cref="Slider"/> will be judged proportionally to the number of ticks hit.
/// </summary>
public bool IgnoreJudgement = true;
[JsonIgnore]
public HitCircle HeadCircle { get; protected set; }
@ -233,7 +239,7 @@ namespace osu.Game.Rulesets.Osu.Objects
HeadCircle.Samples = this.GetNodeSamples(0);
}
public override Judgement CreateJudgement() => new OsuIgnoreJudgement();
public override Judgement CreateJudgement() => IgnoreJudgement ? new OsuIgnoreJudgement() : new OsuJudgement();
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
}

View File

@ -1,13 +1,25 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.Judgements;
namespace osu.Game.Rulesets.Osu.Objects
{
public class SliderHeadCircle : HitCircle
{
/// <summary>
/// Makes the head circle track the follow circle when the start time is reached.
/// Makes this <see cref="SliderHeadCircle"/> track the follow circle when the start time is reached.
/// If <c>false</c>, this <see cref="SliderHeadCircle"/> will be pinned to its initial position in the slider.
/// </summary>
public bool TrackFollowCircle = true;
/// <summary>
/// Whether to treat this <see cref="SliderHeadCircle"/> as a normal <see cref="HitCircle"/> for judgement purposes.
/// If <c>false</c>, judgement will be ignored.
/// </summary>
public bool JudgeAsNormalHitCircle = true;
public override Judgement CreateJudgement() => JudgeAsNormalHitCircle ? base.CreateJudgement() : new OsuIgnoreJudgement();
}
}