mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 20:13:21 +08:00
Move hit events to the ScoreProcessor
This commit is contained in:
parent
ef56225d9a
commit
eab00ec9d9
@ -10,10 +10,15 @@ namespace osu.Game.Rulesets.Osu.Judgements
|
|||||||
{
|
{
|
||||||
public class OsuHitCircleJudgementResult : OsuJudgementResult
|
public class OsuHitCircleJudgementResult : OsuJudgementResult
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="HitCircle"/>.
|
||||||
|
/// </summary>
|
||||||
public HitCircle HitCircle => (HitCircle)HitObject;
|
public HitCircle HitCircle => (HitCircle)HitObject;
|
||||||
|
|
||||||
public Vector2? HitPosition;
|
/// <summary>
|
||||||
public float? Radius;
|
/// The position of the player's cursor when <see cref="HitCircle"/> was hit.
|
||||||
|
/// </summary>
|
||||||
|
public Vector2? CursorPositionAtHit;
|
||||||
|
|
||||||
public OsuHitCircleJudgementResult(HitObject hitObject, Judgement judgement)
|
public OsuHitCircleJudgementResult(HitObject hitObject, Judgement judgement)
|
||||||
: base(hitObject, judgement)
|
: base(hitObject, judgement)
|
||||||
|
@ -142,11 +142,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
|||||||
{
|
{
|
||||||
var circleResult = (OsuHitCircleJudgementResult)r;
|
var circleResult = (OsuHitCircleJudgementResult)r;
|
||||||
|
|
||||||
|
// Todo: This should also consider misses, but they're a little more interesting to handle, since we don't necessarily know the position at the time of a miss.
|
||||||
if (result != HitResult.Miss)
|
if (result != HitResult.Miss)
|
||||||
{
|
{
|
||||||
var localMousePosition = ToLocalSpace(inputManager.CurrentState.Mouse.Position);
|
var localMousePosition = ToLocalSpace(inputManager.CurrentState.Mouse.Position);
|
||||||
circleResult.HitPosition = HitObject.StackedPosition + (localMousePosition - DrawSize / 2);
|
circleResult.CursorPositionAtHit = HitObject.StackedPosition + (localMousePosition - DrawSize / 2);
|
||||||
circleResult.Radius = (float)HitObject.Radius;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
circleResult.Type = result;
|
circleResult.Type = result;
|
||||||
|
@ -29,7 +29,6 @@ using osu.Game.Rulesets.Scoring;
|
|||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Skinning;
|
using osu.Game.Skinning;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Game.Rulesets.Osu.Statistics;
|
using osu.Game.Rulesets.Osu.Statistics;
|
||||||
using osu.Game.Screens.Ranking.Statistics;
|
using osu.Game.Screens.Ranking.Statistics;
|
||||||
@ -201,7 +200,7 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 130,
|
Height = 130,
|
||||||
Child = new TimingDistributionGraph(score.HitEvents.Cast<HitEvent>().ToList())
|
Child = new TimingDistributionGraph(score)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
}
|
}
|
||||||
@ -209,7 +208,7 @@ namespace osu.Game.Rulesets.Osu
|
|||||||
new StatisticContainer("Accuracy Heatmap")
|
new StatisticContainer("Accuracy Heatmap")
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Child = new Heatmap(score.Beatmap, score.HitEvents.Cast<HitEvent>().ToList())
|
Child = new Heatmap(score)
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both
|
RelativeSizeAxes = Axes.Both
|
||||||
}
|
}
|
||||||
|
@ -1,54 +1,16 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Judgements;
|
using osu.Game.Rulesets.Osu.Judgements;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring;
|
|
||||||
using osuTK;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Scoring
|
namespace osu.Game.Rulesets.Osu.Scoring
|
||||||
{
|
{
|
||||||
public class OsuScoreProcessor : ScoreProcessor
|
public class OsuScoreProcessor : ScoreProcessor
|
||||||
{
|
{
|
||||||
private readonly List<HitEvent> hitEvents = new List<HitEvent>();
|
|
||||||
private HitObject lastHitObject;
|
|
||||||
|
|
||||||
protected override void OnResultApplied(JudgementResult result)
|
|
||||||
{
|
|
||||||
base.OnResultApplied(result);
|
|
||||||
|
|
||||||
hitEvents.Add(new HitEvent(result.TimeOffset, result.Type, result.HitObject, lastHitObject, (result as OsuHitCircleJudgementResult)?.HitPosition));
|
|
||||||
lastHitObject = result.HitObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnResultReverted(JudgementResult result)
|
|
||||||
{
|
|
||||||
base.OnResultReverted(result);
|
|
||||||
|
|
||||||
hitEvents.RemoveAt(hitEvents.Count - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void Reset(bool storeResults)
|
|
||||||
{
|
|
||||||
base.Reset(storeResults);
|
|
||||||
|
|
||||||
hitEvents.Clear();
|
|
||||||
lastHitObject = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void PopulateScore(ScoreInfo score)
|
|
||||||
{
|
|
||||||
base.PopulateScore(score);
|
|
||||||
|
|
||||||
score.HitEvents.AddRange(hitEvents.Select(e => e).Cast<object>());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement)
|
protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement)
|
||||||
{
|
{
|
||||||
switch (hitObject)
|
switch (hitObject)
|
||||||
@ -63,42 +25,4 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
|||||||
|
|
||||||
public override HitWindows CreateHitWindows() => new OsuHitWindows();
|
public override HitWindows CreateHitWindows() => new OsuHitWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly struct HitEvent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The time offset from the end of <see cref="HitObject"/> at which the event occurred.
|
|
||||||
/// </summary>
|
|
||||||
public readonly double TimeOffset;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The hit result.
|
|
||||||
/// </summary>
|
|
||||||
public readonly HitResult Result;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="HitObject"/> on which the result occurred.
|
|
||||||
/// </summary>
|
|
||||||
public readonly HitObject HitObject;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The <see cref="HitObject"/> occurring prior to <see cref="HitObject"/>.
|
|
||||||
/// </summary>
|
|
||||||
[CanBeNull]
|
|
||||||
public readonly HitObject LastHitObject;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The player's position offset, if available, at the time of the event.
|
|
||||||
/// </summary>
|
|
||||||
public readonly Vector2? PositionOffset;
|
|
||||||
|
|
||||||
public HitEvent(double timeOffset, HitResult result, HitObject hitObject, [CanBeNull] HitObject lastHitObject, Vector2? positionOffset)
|
|
||||||
{
|
|
||||||
TimeOffset = timeOffset;
|
|
||||||
Result = result;
|
|
||||||
HitObject = hitObject;
|
|
||||||
LastHitObject = lastHitObject;
|
|
||||||
PositionOffset = positionOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,14 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Framework.Layout;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
@ -36,16 +33,11 @@ namespace osu.Game.Rulesets.Osu.Statistics
|
|||||||
|
|
||||||
private GridContainer pointGrid;
|
private GridContainer pointGrid;
|
||||||
|
|
||||||
private readonly BeatmapInfo beatmap;
|
private readonly ScoreInfo score;
|
||||||
private readonly IReadOnlyList<HitEvent> hitEvents;
|
|
||||||
private readonly LayoutValue sizeLayout = new LayoutValue(Invalidation.DrawSize);
|
|
||||||
|
|
||||||
public Heatmap(BeatmapInfo beatmap, IReadOnlyList<HitEvent> hitEvents)
|
public Heatmap(ScoreInfo score)
|
||||||
{
|
{
|
||||||
this.beatmap = beatmap;
|
this.score = score;
|
||||||
this.hitEvents = hitEvents;
|
|
||||||
|
|
||||||
AddLayout(sizeLayout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -149,12 +141,13 @@ namespace osu.Game.Rulesets.Osu.Statistics
|
|||||||
|
|
||||||
pointGrid.Content = points;
|
pointGrid.Content = points;
|
||||||
|
|
||||||
if (hitEvents.Count > 0)
|
if (score.HitEvents == null || score.HitEvents.Count == 0)
|
||||||
{
|
return;
|
||||||
// Todo: This should probably not be done like this.
|
|
||||||
float radius = OsuHitObject.OBJECT_RADIUS * (1.0f - 0.7f * (beatmap.BaseDifficulty.CircleSize - 5) / 5) / 2;
|
|
||||||
|
|
||||||
foreach (var e in hitEvents)
|
// Todo: This should probably not be done like this.
|
||||||
|
float radius = OsuHitObject.OBJECT_RADIUS * (1.0f - 0.7f * (score.Beatmap.BaseDifficulty.CircleSize - 5) / 5) / 2;
|
||||||
|
|
||||||
|
foreach (var e in score.HitEvents)
|
||||||
{
|
{
|
||||||
if (e.LastHitObject == null || e.PositionOffset == null)
|
if (e.LastHitObject == null || e.PositionOffset == null)
|
||||||
continue;
|
continue;
|
||||||
@ -162,7 +155,6 @@ namespace osu.Game.Rulesets.Osu.Statistics
|
|||||||
AddPoint(((OsuHitObject)e.LastHitObject).StackedEndPosition, ((OsuHitObject)e.HitObject).StackedEndPosition, e.PositionOffset.Value, radius);
|
AddPoint(((OsuHitObject)e.LastHitObject).StackedEndPosition, ((OsuHitObject)e.HitObject).StackedEndPosition, e.PositionOffset.Value, radius);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected void AddPoint(Vector2 start, Vector2 end, Vector2 hitPoint, float radius)
|
protected void AddPoint(Vector2 start, Vector2 end, Vector2 hitPoint, float radius)
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
@ -11,7 +10,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Rulesets.Osu.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Statistics
|
namespace osu.Game.Rulesets.Osu.Statistics
|
||||||
{
|
{
|
||||||
@ -37,23 +36,23 @@ namespace osu.Game.Rulesets.Osu.Statistics
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private const float axis_points = 5;
|
private const float axis_points = 5;
|
||||||
|
|
||||||
private readonly List<HitEvent> hitEvents;
|
private readonly ScoreInfo score;
|
||||||
|
|
||||||
public TimingDistributionGraph(List<HitEvent> hitEvents)
|
public TimingDistributionGraph(ScoreInfo score)
|
||||||
{
|
{
|
||||||
this.hitEvents = hitEvents;
|
this.score = score;
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
if (hitEvents.Count == 0)
|
if (score.HitEvents == null || score.HitEvents.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int[] bins = new int[total_timing_distribution_bins];
|
int[] bins = new int[total_timing_distribution_bins];
|
||||||
double binSize = hitEvents.Max(e => Math.Abs(e.TimeOffset)) / timing_distribution_bins;
|
double binSize = score.HitEvents.Max(e => Math.Abs(e.TimeOffset)) / timing_distribution_bins;
|
||||||
|
|
||||||
foreach (var e in hitEvents)
|
foreach (var e in score.HitEvents)
|
||||||
{
|
{
|
||||||
int binOffset = (int)(e.TimeOffset / binSize);
|
int binOffset = (int)(e.TimeOffset / binSize);
|
||||||
bins[timing_distribution_centre_bin_index + binOffset]++;
|
bins[timing_distribution_centre_bin_index + binOffset]++;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Extensions.Color4Extensions;
|
using osu.Framework.Extensions.Color4Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -10,10 +9,9 @@ using osu.Framework.Graphics.Shapes;
|
|||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Rulesets.Osu;
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Osu.Scoring;
|
|
||||||
using osu.Game.Rulesets.Osu.Statistics;
|
using osu.Game.Rulesets.Osu.Statistics;
|
||||||
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
@ -50,7 +48,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
|||||||
{
|
{
|
||||||
Position = new Vector2(100, 300),
|
Position = new Vector2(100, 300),
|
||||||
},
|
},
|
||||||
heatmap = new TestHeatmap(new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo, new List<HitEvent>())
|
heatmap = new TestHeatmap(new ScoreInfo { Beatmap = new TestBeatmap(new OsuRuleset().RulesetInfo).BeatmapInfo })
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
@ -93,8 +91,8 @@ namespace osu.Game.Tests.Visual.Ranking
|
|||||||
|
|
||||||
private class TestHeatmap : Heatmap
|
private class TestHeatmap : Heatmap
|
||||||
{
|
{
|
||||||
public TestHeatmap(BeatmapInfo beatmap, List<HitEvent> events)
|
public TestHeatmap(ScoreInfo score)
|
||||||
: base(beatmap, events)
|
: base(score)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Linq;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -18,7 +17,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
|||||||
{
|
{
|
||||||
var score = new TestScoreInfo(new OsuRuleset().RulesetInfo)
|
var score = new TestScoreInfo(new OsuRuleset().RulesetInfo)
|
||||||
{
|
{
|
||||||
HitEvents = TestSceneTimingDistributionGraph.CreateDistributedHitEvents().Cast<object>().ToList(),
|
HitEvents = TestSceneTimingDistributionGraph.CreateDistributedHitEvents()
|
||||||
};
|
};
|
||||||
|
|
||||||
loadPanel(score);
|
loadPanel(score);
|
||||||
|
@ -7,9 +7,9 @@ using osu.Framework.Extensions.Color4Extensions;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Shapes;
|
using osu.Framework.Graphics.Shapes;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Osu.Scoring;
|
|
||||||
using osu.Game.Rulesets.Osu.Statistics;
|
using osu.Game.Rulesets.Osu.Statistics;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
|
using osu.Game.Scoring;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.Ranking
|
namespace osu.Game.Tests.Visual.Ranking
|
||||||
@ -25,7 +25,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
|||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
Colour = Color4Extensions.FromHex("#333")
|
Colour = Color4Extensions.FromHex("#333")
|
||||||
},
|
},
|
||||||
new TimingDistributionGraph(CreateDistributedHitEvents())
|
new TimingDistributionGraph(new ScoreInfo { HitEvents = CreateDistributedHitEvents() })
|
||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
|
48
osu.Game/Rulesets/Scoring/HitEvent.cs
Normal file
48
osu.Game/Rulesets/Scoring/HitEvent.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// 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 JetBrains.Annotations;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
|
using osuTK;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Scoring
|
||||||
|
{
|
||||||
|
public readonly struct HitEvent
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The time offset from the end of <see cref="HitObject"/> at which the event occurred.
|
||||||
|
/// </summary>
|
||||||
|
public readonly double TimeOffset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The hit result.
|
||||||
|
/// </summary>
|
||||||
|
public readonly HitResult Result;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="HitObject"/> on which the result occurred.
|
||||||
|
/// </summary>
|
||||||
|
public readonly HitObject HitObject;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="HitObject"/> occurring prior to <see cref="HitObject"/>.
|
||||||
|
/// </summary>
|
||||||
|
[CanBeNull]
|
||||||
|
public readonly HitObject LastHitObject;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The player's position offset, if available, at the time of the event.
|
||||||
|
/// </summary>
|
||||||
|
[CanBeNull]
|
||||||
|
public readonly Vector2? PositionOffset;
|
||||||
|
|
||||||
|
public HitEvent(double timeOffset, HitResult result, HitObject hitObject, [CanBeNull] HitObject lastHitObject, [CanBeNull] Vector2? positionOffset)
|
||||||
|
{
|
||||||
|
TimeOffset = timeOffset;
|
||||||
|
Result = result;
|
||||||
|
HitObject = hitObject;
|
||||||
|
LastHitObject = lastHitObject;
|
||||||
|
PositionOffset = positionOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Scoring
|
namespace osu.Game.Rulesets.Scoring
|
||||||
@ -61,6 +62,9 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
private double baseScore;
|
private double baseScore;
|
||||||
private double bonusScore;
|
private double bonusScore;
|
||||||
|
|
||||||
|
private readonly List<HitEvent> hitEvents = new List<HitEvent>();
|
||||||
|
private HitObject lastHitObject;
|
||||||
|
|
||||||
private double scoreMultiplier = 1;
|
private double scoreMultiplier = 1;
|
||||||
|
|
||||||
public ScoreProcessor()
|
public ScoreProcessor()
|
||||||
@ -128,6 +132,9 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
rollingMaxBaseScore += result.Judgement.MaxNumericResult;
|
rollingMaxBaseScore += result.Judgement.MaxNumericResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hitEvents.Add(CreateHitEvent(result));
|
||||||
|
lastHitObject = result.HitObject;
|
||||||
|
|
||||||
updateScore();
|
updateScore();
|
||||||
|
|
||||||
OnResultApplied(result);
|
OnResultApplied(result);
|
||||||
@ -137,6 +144,9 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual HitEvent CreateHitEvent(JudgementResult result)
|
||||||
|
=> new HitEvent(result.TimeOffset, result.Type, result.HitObject, lastHitObject, null);
|
||||||
|
|
||||||
protected sealed override void RevertResultInternal(JudgementResult result)
|
protected sealed override void RevertResultInternal(JudgementResult result)
|
||||||
{
|
{
|
||||||
Combo.Value = result.ComboAtJudgement;
|
Combo.Value = result.ComboAtJudgement;
|
||||||
@ -159,6 +169,10 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
rollingMaxBaseScore -= result.Judgement.MaxNumericResult;
|
rollingMaxBaseScore -= result.Judgement.MaxNumericResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Debug.Assert(hitEvents.Count > 0);
|
||||||
|
lastHitObject = hitEvents[^1].LastHitObject;
|
||||||
|
hitEvents.RemoveAt(hitEvents.Count - 1);
|
||||||
|
|
||||||
updateScore();
|
updateScore();
|
||||||
|
|
||||||
OnResultReverted(result);
|
OnResultReverted(result);
|
||||||
@ -219,6 +233,8 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
base.Reset(storeResults);
|
base.Reset(storeResults);
|
||||||
|
|
||||||
scoreResultCounts.Clear();
|
scoreResultCounts.Clear();
|
||||||
|
hitEvents.Clear();
|
||||||
|
lastHitObject = null;
|
||||||
|
|
||||||
if (storeResults)
|
if (storeResults)
|
||||||
{
|
{
|
||||||
@ -259,6 +275,8 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
|
|
||||||
foreach (var result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r)))
|
foreach (var result in Enum.GetValues(typeof(HitResult)).OfType<HitResult>().Where(r => r > HitResult.None && hitWindows.IsHitResultAllowed(r)))
|
||||||
score.Statistics[result] = GetStatistic(result);
|
score.Statistics[result] = GetStatistic(result);
|
||||||
|
|
||||||
|
score.HitEvents = new List<HitEvent>(hitEvents);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -168,7 +168,7 @@ namespace osu.Game.Scoring
|
|||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<object> HitEvents = new List<object>();
|
public List<HitEvent> HitEvents { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<ScoreFileInfo> Files { get; set; }
|
public List<ScoreFileInfo> Files { get; set; }
|
||||||
|
Loading…
Reference in New Issue
Block a user