// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // 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.Objects; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osuTK; namespace osu.Game.Rulesets.Osu.Scoring { public class OsuScoreProcessor : ScoreProcessor { private readonly List hitEvents = new List(); 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()); } protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) { switch (hitObject) { case HitCircle _: return new OsuHitCircleJudgementResult(hitObject, judgement); default: return new OsuJudgementResult(hitObject, judgement); } } public override HitWindows CreateHitWindows() => new OsuHitWindows(); } public readonly struct HitEvent { /// /// The time offset from the end of at which the event occurred. /// public readonly double TimeOffset; /// /// The hit result. /// public readonly HitResult Result; /// /// The on which the result occurred. /// public readonly HitObject HitObject; /// /// The occurring prior to . /// [CanBeNull] public readonly HitObject LastHitObject; /// /// The player's position offset, if available, at the time of the event. /// 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; } } }