Example #1
0
        /// <summary>
        ///     Handles the replay frames for missed long notes.
        /// </summary>
        private void HandleMissedLongNoteReleases()
        {
            // Handle missed LN releases.
            foreach (var hitObject in ActiveHeldLongNotes)
            {
                var releaseWindow = ScoreProcessor.JudgementWindow[Judgement.Okay] * ScoreProcessor.WindowReleaseMultiplier[Judgement.Okay];

                // Check if the LN's release was missed.
                if (!(Time > hitObject.EndTime + releaseWindow))
                {
                    continue;
                }

                ScoreProcessor.CalculateScore(Judgement.Okay);

                // Add new miss stat.
                var stat = new HitStat(HitStatType.Miss, KeyPressType.None, hitObject, hitObject.EndTime, Judgement.Okay, int.MinValue,
                                       ScoreProcessor.Accuracy, ScoreProcessor.Health);

                ScoreProcessor.Stats.Add(stat);

                // Queue the object to be removed.
                ActiveHeldLongNotesToRemove.Add(hitObject);
            }

            ActiveHeldLongNotesToRemove.ForEach(x => ActiveHeldLongNotes.Remove(x));
        }
Example #2
0
        /// <summary>
        ///     Handles completely missed HitObjects.
        /// </summary>
        private void HandleMissedHitObjects()
        {
            // Handle missed notes.
            foreach (var hitObject in ActiveHitObjects)
            {
                if (Time > hitObject.StartTime + ScoreProcessor.JudgementWindow[Judgement.Okay])
                {
                    // Add a miss to the score.
                    ScoreProcessor.CalculateScore(Judgement.Miss);

                    // Create a new HitStat to add to the ScoreProcessor.
                    var stat = new HitStat(HitStatType.Miss, KeyPressType.None, hitObject, hitObject.StartTime, Judgement.Miss, int.MinValue,
                                           ScoreProcessor.Accuracy, ScoreProcessor.Health);

                    ScoreProcessor.Stats.Add(stat);

                    // Long notes count as two misses, so add another one if the object is one.
                    if (hitObject.IsLongNote)
                    {
                        ScoreProcessor.CalculateScore(Judgement.Miss);
                        ScoreProcessor.Stats.Add(stat);
                    }

                    ActiveHitObjectsToRemove.Add(hitObject);
                }
                else
                {
                    break;
                }
            }

            // Remove all objects
            ActiveHitObjectsToRemove.ForEach(x => ActiveHitObjects.Remove(x));
            ActiveHeldLongNotesToRemove.ForEach(x => ActiveHeldLongNotes.Remove(x));
        }
Example #3
0
        /// <summary>
        ///     Handles all key presses in the current replay frame.
        /// </summary>
        private void HandleKeyPressesInFrame()
        {
            // Retrieve a list of the key press states in integer form.
            var currentFramePressed  = Replay.KeyPressStateToLanes(Replay.Frames[CurrentFrame].Keys);
            var previousFramePressed = CurrentFrame > 0 ? Replay.KeyPressStateToLanes(Replay.Frames[CurrentFrame - 1].Keys) : new List <int>();

            // Update the key press state in the store.
            for (var i = 0; i < InputKeyStore.Count; i++)
            {
                InputKeyStore[i].Pressed = currentFramePressed.Contains(i);
            }

            // Check the difference in key press states for the current and previous frames.
            var keyDifferences = currentFramePressed.Except(previousFramePressed)
                                 .Concat(previousFramePressed.Except(currentFramePressed))
                                 .ToList();

            // Go through each frame and handle key presses/releases.
            foreach (var key in keyDifferences)
            {
                // This key was uniquely pressed during this frame.
                if (currentFramePressed.Contains(key))
                {
                    // Find the nearest object in the lane that the user has pressed.
                    var nearestObjectIndex = GetIndexOfNearestLaneObject(key + 1, Time);

                    if (nearestObjectIndex == -1)
                    {
                        continue;
                    }

                    // Grab the actual HitObject instance.
                    var hitObject = ActiveHitObjects[nearestObjectIndex];

                    // Calculate the hit difference.
                    var hitDifference = hitObject.StartTime - Time;

                    // Calculate Score.
                    var judgement = ScoreProcessor.CalculateScore(hitDifference, KeyPressType.Press);

                    switch (judgement)
                    {
                    // Don't handle ghost key presses, so just continue further.
                    case Judgement.Ghost:
                        continue;

                    // Object needs to be removed completely if it's a miss.
                    case Judgement.Miss:
                        // Add another miss for an LN (head and tail)
                        if (hitObject.IsLongNote)
                        {
                            ScoreProcessor.CalculateScore(Judgement.Miss);
                            ScoreProcessor.Stats.Add(new HitStat(HitStatType.Miss, KeyPressType.Press, hitObject, Time, Judgement.Miss, int.MinValue,
                                                                 ScoreProcessor.Accuracy, ScoreProcessor.Health));
                        }
                        break;

                    default:
                        // Long notes need to be changed to a held status.
                        if (hitObject.IsLongNote)
                        {
                            ActiveHeldLongNotes.Add(hitObject);
                        }
                        break;
                    }

                    // Add a new hit stat to the score processor.
                    var stat = new HitStat(HitStatType.Hit, KeyPressType.Press, hitObject, Time, judgement, hitDifference,
                                           ScoreProcessor.Accuracy, ScoreProcessor.Health);

                    ScoreProcessor.Stats.Add(stat);

                    // Object needs to be removed from ActiveObjects.
                    ActiveHitObjectsToRemove.Add(hitObject);
                }
                // This key was uniquely released during this frame.
                else if (previousFramePressed.Contains(key))
                {
                    // Find the index of the actual closest LN and handle the key release
                    // if so.
                    foreach (var hitObject in ActiveHeldLongNotes)
                    {
                        // Handle the release of the note.
                        if (hitObject.Lane != key + 1)
                        {
                            continue;
                        }

                        // Calculate the hit difference.
                        var hitDifference = hitObject.EndTime - Time;

                        // Calculate Score
                        var judgement = ScoreProcessor.CalculateScore(hitDifference, KeyPressType.Release);

                        // LN was released during a hit window.
                        if (judgement != Judgement.Ghost)
                        {
                            // Add a new hit stat to the score processor.
                            var stat = new HitStat(HitStatType.Hit, KeyPressType.Release, hitObject, Time, judgement, hitDifference,
                                                   ScoreProcessor.Accuracy, ScoreProcessor.Health);

                            ScoreProcessor.Stats.Add(stat);
                        }
                        // The LN was released too early (miss)
                        else
                        {
                            ScoreProcessor.CalculateScore(Judgement.Miss);

                            // Add a new stat to ScoreProcessor.
                            var stat = new HitStat(HitStatType.Hit, KeyPressType.Release, hitObject, Time, Judgement.Miss, hitDifference,
                                                   ScoreProcessor.Accuracy, ScoreProcessor.Health);

                            ScoreProcessor.Stats.Add(stat);
                        }

                        // Remove the object from its held state.
                        ActiveHeldLongNotesToRemove.Add(hitObject);
                    }
                }
            }

            // Remove all active objects after handling key presses/releases.
            ActiveHitObjectsToRemove.ForEach(x => ActiveHitObjects.Remove(x));
            ActiveHeldLongNotesToRemove.ForEach(x => ActiveHeldLongNotes.Remove(x));
        }