/// <summary> /// Keeps track of and plays object hitsounds. /// </summary> private void PlayHitsounds() { for (var i = HitSoundObjectIndex; i < WorkingMap.HitObjects.Count; i++) { if (Exiting) { return; } var obj = WorkingMap.HitObjects[i]; if (AudioEngine.Track.Time >= obj.StartTime) { var view = (EditorScreenView)View; if (!view.LayerCompositor.ScrollContainer.AvailableItems[obj.EditorLayer].Hidden) { if (ConfigManager.EditorEnableHitsounds.Value) { HitObjectManager.PlayObjectHitSounds(obj); } if (ConfigManager.EditorEnableKeysounds.Value) { HitObjectManager.PlayObjectKeySounds(obj); } } HitSoundObjectIndex = i + 1; } else { break; } } }
/// <summary> /// Handles an individual key press during gameplay. /// </summary> /// <param name="manager"></param> /// <param name="gameplayHitObject"></param> /// <param name="objectIndex"></param> private void HandleKeyPress(HitObjectManagerKeys manager, GameplayHitObjectKeys gameplayHitObject) { // Play the HitSounds of closest hit object. if (ConfigManager.EnableHitsounds.Value) { HitObjectManager.PlayObjectHitSounds(gameplayHitObject.Info); } if (ConfigManager.EnableKeysounds.Value) { HitObjectManager.PlayObjectKeySounds(gameplayHitObject.Info); } // Get Judgement and references var time = (int)manager.CurrentAudioPosition; var hitDifference = gameplayHitObject.Info.StartTime - time; var judgement = ((ScoreProcessorKeys)Ruleset.ScoreProcessor).CalculateScore(hitDifference, KeyPressType.Press, ReplayInputManager == null); var lane = gameplayHitObject.Info.Lane - 1; // Ignore Ghost Taps if (judgement == Judgement.Ghost) { return; } // Remove HitObject from Object Pool. Will be recycled/killed as necessary. gameplayHitObject = manager.ActiveNoteLanes[lane].Dequeue(); // Update stats Ruleset.ScoreProcessor.Stats.Add( new HitStat( HitStatType.Hit, KeyPressType.Press, gameplayHitObject.Info, time, judgement, hitDifference, Ruleset.ScoreProcessor.Accuracy, Ruleset.ScoreProcessor.Health )); // Update Scoreboard var view = (GameplayScreenView)Ruleset.Screen.View; view.UpdateScoreboardUsers(); view.UpdateScoreAndAccuracyDisplays(); // Update Playfield var playfield = (GameplayPlayfieldKeys)Ruleset.Playfield; if (ReplayInputManager == null) { playfield.Stage.ComboDisplay.MakeVisible(); playfield.Stage.HitError.AddJudgement(judgement, gameplayHitObject.Info.StartTime - manager.CurrentAudioPosition); playfield.Stage.JudgementHitBurst.PerformJudgementAnimation(judgement); } // Update Object Pooling switch (judgement) { // Handle early miss cases here. case Judgement.Miss when gameplayHitObject.Info.IsLongNote: // Add another miss when hit missing LNS ((ScoreProcessorKeys)Ruleset.ScoreProcessor).CalculateScore(Judgement.Miss); Ruleset.ScoreProcessor.Stats.Add( new HitStat( HitStatType.Miss, KeyPressType.Press, gameplayHitObject.Info, time, Judgement.Miss, time, Ruleset.ScoreProcessor.Accuracy, Ruleset.ScoreProcessor.Health )); view.UpdateScoreboardUsers(); view.UpdateScoreAndAccuracyDisplays(); playfield.Stage.JudgementHitBurst.PerformJudgementAnimation(Judgement.Miss); manager.KillPoolObject(gameplayHitObject); break; // Handle miss cases. case Judgement.Miss: manager.RecyclePoolObject(gameplayHitObject); break; // Handle non-miss cases. Perform Hit Lighting Animation and Handle Object pooling. default: playfield.Stage.HitLightingObjects[lane].PerformHitAnimation(gameplayHitObject.Info.IsLongNote); if (gameplayHitObject.Info.IsLongNote) { manager.ChangePoolObjectStatusToHeld(gameplayHitObject); gameplayHitObject.StartLongNoteAnimation(); } else { manager.RecyclePoolObject(gameplayHitObject); } break; } }