mirror of
https://github.com/ppy/osu
synced 2024-12-29 10:22:43 +00:00
Merge branch 'master' into less-basic-touchscreen-detection
This commit is contained in:
commit
febd004bda
@ -41,11 +41,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
switch (hitObject)
|
||||
{
|
||||
case Slider slider:
|
||||
slider.OnlyJudgeNestedObjects = !NoSliderHeadAccuracy.Value;
|
||||
|
||||
foreach (var head in slider.NestedHitObjects.OfType<SliderHeadCircle>())
|
||||
head.JudgeAsNormalHitCircle = !NoSliderHeadAccuracy.Value;
|
||||
|
||||
slider.ClassicSliderBehaviour = NoSliderHeadAccuracy.Value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
/// </summary>
|
||||
public Container OverlayElementContainer { get; private set; }
|
||||
|
||||
public override bool DisplayResult => !HitObject.OnlyJudgeNestedObjects;
|
||||
public override bool DisplayResult => HitObject.ClassicSliderBehaviour;
|
||||
|
||||
[CanBeNull]
|
||||
public PlaySliderBody SliderBody => Body.Drawable as PlaySliderBody;
|
||||
@ -272,30 +272,31 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
if (userTriggered || !TailCircle.Judged || Time.Current < HitObject.EndTime)
|
||||
return;
|
||||
|
||||
// If only the nested hitobjects are judged, then the slider's own judgement is ignored for scoring purposes.
|
||||
// But the slider needs to still be judged with a reasonable hit/miss result for visual purposes (hit/miss transforms, etc).
|
||||
if (HitObject.OnlyJudgeNestedObjects)
|
||||
if (HitObject.ClassicSliderBehaviour)
|
||||
{
|
||||
ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, if this slider also needs to be judged, apply judgement proportionally to the number of nested hitobjects hit. This is the classic osu!stable scoring.
|
||||
ApplyResult(r =>
|
||||
{
|
||||
int totalTicks = NestedHitObjects.Count;
|
||||
int hitTicks = NestedHitObjects.Count(h => h.IsHit);
|
||||
|
||||
if (hitTicks == totalTicks)
|
||||
r.Type = HitResult.Great;
|
||||
else if (hitTicks == 0)
|
||||
r.Type = HitResult.Miss;
|
||||
else
|
||||
// Classic behaviour means a slider is judged proportionally to the number of nested hitobjects hit. This is the classic osu!stable scoring.
|
||||
ApplyResult(r =>
|
||||
{
|
||||
double hitFraction = (double)hitTicks / totalTicks;
|
||||
r.Type = hitFraction >= 0.5 ? HitResult.Ok : HitResult.Meh;
|
||||
}
|
||||
});
|
||||
int totalTicks = NestedHitObjects.Count;
|
||||
int hitTicks = NestedHitObjects.Count(h => h.IsHit);
|
||||
|
||||
if (hitTicks == totalTicks)
|
||||
r.Type = HitResult.Great;
|
||||
else if (hitTicks == 0)
|
||||
r.Type = HitResult.Miss;
|
||||
else
|
||||
{
|
||||
double hitFraction = (double)hitTicks / totalTicks;
|
||||
r.Type = hitFraction >= 0.5 ? HitResult.Ok : HitResult.Meh;
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// If only the nested hitobjects are judged, then the slider's own judgement is ignored for scoring purposes.
|
||||
// But the slider needs to still be judged with a reasonable hit/miss result for visual purposes (hit/miss transforms, etc).
|
||||
ApplyResult(r => r.Type = NestedHitObjects.Any(h => h.Result.IsHit) ? r.Judgement.MaxResult : r.Judgement.MinResult);
|
||||
}
|
||||
}
|
||||
|
||||
public override void PlaySamples()
|
||||
|
@ -16,7 +16,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
public DrawableSlider DrawableSlider => (DrawableSlider)ParentHitObject;
|
||||
|
||||
public override bool DisplayResult => HitObject?.JudgeAsNormalHitCircle ?? base.DisplayResult;
|
||||
public override bool DisplayResult
|
||||
{
|
||||
get
|
||||
{
|
||||
if (HitObject?.ClassicSliderBehaviour == true)
|
||||
return false;
|
||||
|
||||
return base.DisplayResult;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly IBindable<int> pathVersion = new Bindable<int>();
|
||||
|
||||
@ -56,12 +65,16 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
Debug.Assert(HitObject != null);
|
||||
|
||||
if (HitObject.JudgeAsNormalHitCircle)
|
||||
return base.ResultFor(timeOffset);
|
||||
if (HitObject.ClassicSliderBehaviour)
|
||||
{
|
||||
// With classic slider behaviour, heads are considered fully hit if in the largest hit window.
|
||||
// We can't award a full Great because the true Great judgement is awarded on the Slider itself,
|
||||
// reduced based on number of ticks hit,
|
||||
// so we use the most suitable LargeTick judgement here instead.
|
||||
return base.ResultFor(timeOffset).IsHit() ? HitResult.LargeTickHit : HitResult.LargeTickMiss;
|
||||
}
|
||||
|
||||
// If not judged as a normal hitcircle, judge as a slider tick instead. This is the classic osu!stable scoring.
|
||||
var result = base.ResultFor(timeOffset);
|
||||
return result.IsHit() ? HitResult.LargeTickHit : HitResult.LargeTickMiss;
|
||||
return base.ResultFor(timeOffset);
|
||||
}
|
||||
|
||||
public override void Shake()
|
||||
|
@ -124,10 +124,21 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
public double TickDistanceMultiplier = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this <see cref="Slider"/>'s judgement is fully handled by its nested <see cref="HitObject"/>s.
|
||||
/// If <c>false</c>, this <see cref="Slider"/> will be judged proportionally to the number of nested <see cref="HitObject"/>s hit.
|
||||
/// If <see langword="false"/>, <see cref="Slider"/>'s judgement is fully handled by its nested <see cref="HitObject"/>s.
|
||||
/// If <see langword="true"/>, this <see cref="Slider"/> will be judged proportionally to the number of nested <see cref="HitObject"/>s hit.
|
||||
/// </summary>
|
||||
public bool OnlyJudgeNestedObjects = true;
|
||||
public bool ClassicSliderBehaviour
|
||||
{
|
||||
get => classicSliderBehaviour;
|
||||
set
|
||||
{
|
||||
classicSliderBehaviour = value;
|
||||
if (HeadCircle != null)
|
||||
HeadCircle.ClassicSliderBehaviour = value;
|
||||
}
|
||||
}
|
||||
|
||||
private bool classicSliderBehaviour;
|
||||
|
||||
public BindableNumber<double> SliderVelocityMultiplierBindable { get; } = new BindableDouble(1)
|
||||
{
|
||||
@ -187,7 +198,6 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
StartTime = e.Time,
|
||||
Position = Position + Path.PositionAt(e.PathProgress),
|
||||
StackHeight = StackHeight,
|
||||
Scale = Scale,
|
||||
});
|
||||
break;
|
||||
|
||||
@ -197,6 +207,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
StartTime = e.Time,
|
||||
Position = Position,
|
||||
StackHeight = StackHeight,
|
||||
ClassicSliderBehaviour = ClassicSliderBehaviour,
|
||||
});
|
||||
break;
|
||||
|
||||
@ -206,7 +217,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
RepeatIndex = e.SpanIndex,
|
||||
StartTime = e.Time,
|
||||
Position = EndPosition,
|
||||
StackHeight = StackHeight
|
||||
StackHeight = StackHeight,
|
||||
});
|
||||
break;
|
||||
|
||||
@ -217,7 +228,6 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
StartTime = StartTime + (e.SpanIndex + 1) * SpanDuration,
|
||||
Position = Position + Path.PositionAt(e.PathProgress),
|
||||
StackHeight = StackHeight,
|
||||
Scale = Scale,
|
||||
});
|
||||
break;
|
||||
}
|
||||
@ -262,7 +272,11 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
TailSamples = this.GetNodeSamples(repeatCount + 1);
|
||||
}
|
||||
|
||||
public override Judgement CreateJudgement() => OnlyJudgeNestedObjects ? new OsuIgnoreJudgement() : new OsuJudgement();
|
||||
public override Judgement CreateJudgement() => ClassicSliderBehaviour
|
||||
// See logic in `DrawableSlider.CheckForResult()`
|
||||
? new OsuJudgement()
|
||||
// Of note, this creates a combo discrepancy for non-classic-mod sliders (there is no combo increase for tail or slider judgement).
|
||||
: new OsuIgnoreJudgement();
|
||||
|
||||
protected override HitWindows CreateHitWindows() => HitWindows.Empty;
|
||||
}
|
||||
|
@ -9,11 +9,11 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
public class SliderHeadCircle : HitCircle
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether to treat this <see cref="SliderHeadCircle"/> as a normal <see cref="HitCircle"/> for judgement purposes.
|
||||
/// If <c>false</c>, this <see cref="SliderHeadCircle"/> will be judged as a <see cref="SliderTick"/> instead.
|
||||
/// If <see langword="false"/>, treat this <see cref="SliderHeadCircle"/> as a normal <see cref="HitCircle"/> for judgement purposes.
|
||||
/// If <see langword="true"/>, this <see cref="SliderHeadCircle"/> will be judged as a <see cref="SliderTick"/> instead.
|
||||
/// </summary>
|
||||
public bool JudgeAsNormalHitCircle = true;
|
||||
public bool ClassicSliderBehaviour;
|
||||
|
||||
public override Judgement CreateJudgement() => JudgeAsNormalHitCircle ? base.CreateJudgement() : new SliderTickJudgement();
|
||||
public override Judgement CreateJudgement() => ClassicSliderBehaviour ? new SliderTickJudgement() : base.CreateJudgement();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user