diff --git a/Quaver.API/Enums/HitObjectType.cs b/Quaver.API/Enums/HitObjectType.cs deleted file mode 100644 index 0e9a48027..000000000 --- a/Quaver.API/Enums/HitObjectType.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Quaver.API.Enums -{ - /// - /// Indicates the type of a hit object - /// - public enum HitObjectType - { - Normal, // Regular hit object. It should be hit normally. - Mine // A mine object. It should not be hit, and hitting it will result in a miss. - } -} \ No newline at end of file diff --git a/Quaver.API/Maps/Processors/Difficulty/Rulesets/Keys/DifficultyProcessorKeys.cs b/Quaver.API/Maps/Processors/Difficulty/Rulesets/Keys/DifficultyProcessorKeys.cs index eb6fb4edc..021e4918a 100644 --- a/Quaver.API/Maps/Processors/Difficulty/Rulesets/Keys/DifficultyProcessorKeys.cs +++ b/Quaver.API/Maps/Processors/Difficulty/Rulesets/Keys/DifficultyProcessorKeys.cs @@ -137,7 +137,7 @@ public DifficultyProcessorKeys(Qua map, StrainConstants constants, ModIdentifier StrainConstants = (StrainConstantsKeys)constants; // Don't bother calculating map difficulty if there's less than 2 hit objects - if (map.DifficultyContributingHitObjects < 2) + if (map.HitObjects.Count < 2) return; // Solve for difficulty @@ -203,8 +203,6 @@ private void ComputeBaseStrainStates(float rate, Hand assumeHand) { if (Map.HasScratchKey && Map.HitObjects[i].Lane == Map.GetKeyCount()) continue; - if (Map.HitObjects[i].Type == HitObjectType.Mine) - continue; var curHitOb = new StrainSolverHitObject(Map.HitObjects[i]); var curStrainData = new StrainSolverData(curHitOb, rate); @@ -677,7 +675,7 @@ private float CalculateOverallDifficulty() private void ComputeNoteDensityData(float rate) { //MapLength = Qua.Length; - AverageNoteDensity = SECONDS_TO_MILLISECONDS * Map.DifficultyContributingHitObjects / (Map.Length * (-.5f * rate + 1.5f)); + AverageNoteDensity = SECONDS_TO_MILLISECONDS * Map.HitObjects.Count / (Map.Length * (-.5f * rate + 1.5f)); } /// diff --git a/Quaver.API/Maps/Processors/Scoring/ScoreProcessor.cs b/Quaver.API/Maps/Processors/Scoring/ScoreProcessor.cs index a07dc1db2..70b866c6e 100644 --- a/Quaver.API/Maps/Processors/Scoring/ScoreProcessor.cs +++ b/Quaver.API/Maps/Processors/Scoring/ScoreProcessor.cs @@ -223,7 +223,7 @@ public ScoreProcessor(Replay replay, JudgementWindows windows = null) /// /// Adds a judgement to the score and recalculates the score. /// - public abstract void CalculateScore(Judgement judgement, bool isLongNoteRelease = false, bool isMine = false); + public abstract void CalculateScore(Judgement judgement, bool isLongNoteRelease = false); /// /// Calculates the accuracy of the current play session. diff --git a/Quaver.API/Maps/Processors/Scoring/ScoreProcessorKeys.cs b/Quaver.API/Maps/Processors/Scoring/ScoreProcessorKeys.cs index 47fd8ded6..f679c4ff9 100644 --- a/Quaver.API/Maps/Processors/Scoring/ScoreProcessorKeys.cs +++ b/Quaver.API/Maps/Processors/Scoring/ScoreProcessorKeys.cs @@ -14,7 +14,6 @@ using Quaver.API.Maps.Processors.Scoring.Data; using Quaver.API.Maps.Processors.Scoring.Multiplayer; using Quaver.API.Replays; -using HitObjectType = Quaver.API.Enums.HitObjectType; namespace Quaver.API.Maps.Processors.Scoring { @@ -174,9 +173,7 @@ public ScoreProcessorKeys(Replay replay, JudgementWindows windows = null) : base /// /// /// - /// - public Judgement CalculateScore(int hitDifference, KeyPressType keyPressType, bool calculateAllStats = true, - bool isMine = false) + public Judgement CalculateScore(int hitDifference, KeyPressType keyPressType, bool calculateAllStats = true) { var absoluteDifference = 0; @@ -225,25 +222,18 @@ public Judgement CalculateScore(int hitDifference, KeyPressType keyPressType, bo return judgement; if (calculateAllStats) - CalculateScore(judgement, keyPressType == KeyPressType.Release, isMine); + CalculateScore(judgement, keyPressType == KeyPressType.Release); return judgement; } - public void CalculateScore(HitStat hitStat) - { - CalculateScore(hitStat.Judgement, hitStat.KeyPressType == KeyPressType.Release, - hitStat.HitObject.Type is HitObjectType.Mine); - } - /// /// /// Calculate Score and Health increase/decrease with a given judgement. /// /// /// - /// - public override void CalculateScore(Judgement judgement, bool isLongNoteRelease = false, bool isMine = false) + public override void CalculateScore(Judgement judgement, bool isLongNoteRelease = false) { // Update Judgement count CurrentJudgements[judgement]++; @@ -267,9 +257,7 @@ public override void CalculateScore(Judgement judgement, bool isLongNoteRelease MultiplierCount++; // Add to the combo since the user hit. - // Only do this when the note is not a mine (so it is a regular note) - if (!isMine) - Combo++; + Combo++; // Set the max combo if applicable. if (Combo > MaxCombo) @@ -384,7 +372,17 @@ protected override void InitializeHealthWeighting() /// public int GetTotalJudgementCount() { - return Map.HitObjects.Sum(o => o.JudgementCount); + var judgements = 0; + + foreach (var o in Map.HitObjects) + { + if (o.IsLongNote) + judgements += 2; + else + judgements++; + } + + return judgements; } /// diff --git a/Quaver.API/Maps/Qua.cs b/Quaver.API/Maps/Qua.cs index 67256f48d..e51b41e68 100644 --- a/Quaver.API/Maps/Qua.cs +++ b/Quaver.API/Maps/Qua.cs @@ -185,19 +185,6 @@ public List ScrollSpeedFactors /// public List HitObjects { get; private set; } = new List(); - /// - /// Number of mines in the map - /// - [YamlIgnore] - public int MineCount => HitObjects.Count(x => x.Type is HitObjectType.Mine); - - /// - /// Number of notes counted for diffcalc. - /// Currently, it's every note except mines - /// - [YamlIgnore] - public int DifficultyContributingHitObjects => HitObjects.Count - MineCount; - public Dictionary TimingGroups { get; private set; } = new Dictionary(); @@ -372,8 +359,7 @@ static HitObjectInfo SerializableHitObject(HitObjectInfo obj) => .Select(x => new KeySoundInfo { Sample = x.Sample, Volume = x.Volume == 100 ? 0 : x.Volume }) .ToList(), Lane = obj.Lane, StartTime = obj.StartTime, - TimingGroup = obj.TimingGroup == DefaultScrollGroupId ? null : obj.TimingGroup, - Type = obj.Type + TimingGroup = obj.TimingGroup == DefaultScrollGroupId ? null : obj.TimingGroup }; static SoundEffectInfo SerializableSoundEffect(SoundEffectInfo x) => @@ -1115,15 +1101,8 @@ public HitObjectInfo GetHitObjectAtJudgementIndex(int index) // ReSharper disable once ForeachCanBeConvertedToQueryUsingAnotherGetEnumerator foreach (var h in HitObjects) - { - var judgementCount = h.JudgementCount; - if (total <= index && index < total + judgementCount) - { + if (total++ == index || (h.IsLongNote && total++ == index)) return h; - } - - total += judgementCount; - } return null; } diff --git a/Quaver.API/Maps/Structures/HitObjectInfo.cs b/Quaver.API/Maps/Structures/HitObjectInfo.cs index 197e32ddf..6aa26f73c 100644 --- a/Quaver.API/Maps/Structures/HitObjectInfo.cs +++ b/Quaver.API/Maps/Structures/HitObjectInfo.cs @@ -64,11 +64,6 @@ public HitSounds HitSound set; } - /// - /// The hit object could be a normal note or a mine - /// - public HitObjectType Type { get; [MoonSharpVisible(false)] set; } - /// /// Key sounds to play when this object is hit. /// @@ -100,11 +95,6 @@ public string TimingGroup [YamlIgnore] public bool IsLongNote => EndTime > 0; - /// - /// The number of judgements generated by this object - /// - [YamlIgnore] public int JudgementCount => IsLongNote && Type != HitObjectType.Mine ? 2 : 1; - /// /// Returns if the object is allowed to be edited in lua scripts /// @@ -185,7 +175,6 @@ public bool Equals(HitObjectInfo x, HitObjectInfo y) x.Lane == y.Lane && x.EndTime == y.EndTime && x.HitSound == y.HitSound && - x.Type == y.Type && x.KeySounds.SequenceEqual(y.KeySounds, KeySoundInfo.ByValueComparer) && x.EditorLayer == y.EditorLayer; } @@ -197,7 +186,6 @@ public int GetHashCode(HitObjectInfo obj) var hashCode = obj.StartTime; hashCode = (hashCode * 397) ^ obj.Lane; hashCode = (hashCode * 397) ^ obj.EndTime; - hashCode = (hashCode * 397) ^ (int)obj.Type; hashCode = (hashCode * 397) ^ (int)obj.HitSound; foreach (var keySound in obj.KeySounds) diff --git a/Quaver.API/Replays/Replay.cs b/Quaver.API/Replays/Replay.cs index 75d183d17..3458e0d39 100644 --- a/Quaver.API/Replays/Replay.cs +++ b/Quaver.API/Replays/Replay.cs @@ -332,9 +332,6 @@ public static Replay GeneratePerfectReplayKeys(Replay replay, Qua map) foreach (var hitObject in map.HitObjects) { - if (hitObject.Type is HitObjectType.Mine) - continue; - // Add key press frame nonCombined.Add(new ReplayAutoplayFrame(hitObject, ReplayAutoplayFrameType.Press, hitObject.StartTime, KeyLaneToPressState(hitObject.Lane))); diff --git a/Quaver.API/Replays/Virtual/VirtualReplayPlayer.cs b/Quaver.API/Replays/Virtual/VirtualReplayPlayer.cs index bda071c0b..1e07de56a 100644 --- a/Quaver.API/Replays/Virtual/VirtualReplayPlayer.cs +++ b/Quaver.API/Replays/Virtual/VirtualReplayPlayer.cs @@ -33,18 +33,6 @@ public class VirtualReplayPlayer /// The score processor for the virtual replay. /// public ScoreProcessorKeys ScoreProcessor { get; } - - - /// - /// All of the mines that are currently active and available. - /// - public List ActiveMines { get; } - - - /// - /// The list of active mines that are scheduled for removal. - /// - public List ActiveMinesToRemove { get; set; } /// /// All of the HitObjects that are currently active and available. @@ -108,22 +96,8 @@ public VirtualReplayPlayer(Replay replay, Qua map, JudgementWindows windows = nu ActiveHitObjects = new List(); ActiveHeldLongNotes = new List(); - ActiveMines = new List(); - map.HitObjects.ForEach(x => - { - switch (x.Type) - { - case HitObjectType.Normal: - ActiveHitObjects.Add(x); - break; - case HitObjectType.Mine: - ActiveMines.Add(x); - break; - default: - throw new ArgumentOutOfRangeException(); - } - }); + map.HitObjects.ForEach(x => ActiveHitObjects.Add(x)); // Add virtual key bindings based on the game mode of the replay. InputKeyStore = new List(); @@ -153,12 +127,10 @@ public void PlayNextFrame() { var obj = Map.GetHitObjectAtJudgementIndex(i); - var hitStat = new HitStat(HitStatType.Miss, KeyPressType.None, obj, obj.StartTime, - Judgement.Miss, int.MinValue, ScoreProcessor.Accuracy, ScoreProcessor.Health); - - ScoreProcessor.CalculateScore(hitStat); + ScoreProcessor.CalculateScore(Judgement.Miss); - ScoreProcessor.Stats.Add(hitStat); + ScoreProcessor.Stats.Add(new HitStat(HitStatType.Miss, KeyPressType.None, obj, obj.StartTime, + Judgement.Miss, int.MinValue, ScoreProcessor.Accuracy, ScoreProcessor.Health)); if (!ScoreProcessor.Failed) continue; @@ -178,7 +150,6 @@ public void PlayNextFrame() // Store the objects that need to be removed from the list of active objects. ActiveHitObjectsToRemove = new List(); ActiveHeldLongNotesToRemove = new List(); - ActiveMinesToRemove = new List(); if (CurrentFrame < Replay.Frames.Count) { @@ -215,8 +186,6 @@ 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(); - - var previousFrameTime = CurrentFrame > 0 ? Replay.Frames[CurrentFrame - 1].Time : Time; // Update the key press state in the store. for (var i = 0; i < InputKeyStore.Count; i++) @@ -227,40 +196,6 @@ private void HandleKeyPressesInFrame() .Concat(previousFramePressed.Except(currentFramePressed)) .ToList(); - // Handle mines that were hit between frames. - // The previous frame's pressed keys are held up until now, so [previousFrameTime..Time) - // is the interval to check for mine hits. - foreach (var lane in previousFramePressed) - { - foreach (var mine in ActiveMines) - { - // Check for any mines that were hit between the previous and the current frame - var endTime = mine.IsLongNote ? mine.EndTime : mine.StartTime; - if (mine.Lane == lane + 1 - && endTime + ScoreProcessor.JudgementWindow[Judgement.Marv] > previousFrameTime - && Time >= mine.StartTime - ScoreProcessor.JudgementWindow[Judgement.Marv]) - { - // Calculate the hit difference. - // If this lane had been pressed before the mine appeared, give maximum early hit window - // If pressed somewhere within the mine's hit window, accurate hit error can be given - var hitDifference = - mine.StartTime - ScoreProcessor.JudgementWindow[Judgement.Marv] > previousFrameTime - ? (int)ScoreProcessor.JudgementWindow[Judgement.Marv] - : mine.StartTime - previousFrameTime; - - // Add a new hit stat to the score processor. - var stat = new HitStat(HitStatType.Miss, KeyPressType.Press, mine, Time, Judgement.Miss, hitDifference, - ScoreProcessor.Accuracy, ScoreProcessor.Health); - - ScoreProcessor.CalculateScore(stat); - ScoreProcessor.Stats.Add(stat); - - // Object needs to be removed from ActiveObjects. - ActiveMinesToRemove.Add(mine); - } - } - } - // Go through each frame and handle key presses/releases. foreach (var key in keyDifferences) { @@ -286,7 +221,7 @@ private void HandleKeyPressesInFrame() var hitDifference = hitObject.StartTime - Time; // Calculate Score. - var judgement = ScoreProcessor.CalculateScore(hitDifference, KeyPressType.Press, isMine: false); + var judgement = ScoreProcessor.CalculateScore(hitDifference, KeyPressType.Press); switch (judgement) { @@ -298,7 +233,7 @@ private void HandleKeyPressesInFrame() // Add another miss for an LN (head and tail) if (hitObject.IsLongNote) { - ScoreProcessor.CalculateScore(Judgement.Miss, true, false); + ScoreProcessor.CalculateScore(Judgement.Miss, true); ScoreProcessor.Stats.Add(new HitStat(HitStatType.Miss, KeyPressType.Press, hitObject, Time, Judgement.Miss, int.MinValue, ScoreProcessor.Accuracy, ScoreProcessor.Health)); @@ -335,7 +270,7 @@ private void HandleKeyPressesInFrame() var hitDifference = hitObject.EndTime - Time; // Calculate Score - var judgement = ScoreProcessor.CalculateScore(hitDifference, KeyPressType.Release, isMine: false); + var judgement = ScoreProcessor.CalculateScore(hitDifference, KeyPressType.Release); // LN was released during a hit window. if (judgement != Judgement.Ghost && judgement != Judgement.Miss) @@ -349,7 +284,7 @@ private void HandleKeyPressesInFrame() // The LN was released too early (miss) else { - ScoreProcessor.CalculateScore(Judgement.Miss, true, false); + ScoreProcessor.CalculateScore(Judgement.Miss, true); // Add a new stat to ScoreProcessor. var stat = new HitStat(HitStatType.Hit, KeyPressType.Release, hitObject, Time, Judgement.Miss, hitDifference, @@ -367,7 +302,6 @@ private void HandleKeyPressesInFrame() // Remove all active objects after handling key presses/releases. ActiveHitObjectsToRemove.ForEach(x => ActiveHitObjects.Remove(x)); ActiveHeldLongNotesToRemove.ForEach(x => ActiveHeldLongNotes.Remove(x)); - ActiveMinesToRemove.ForEach(x => ActiveMines.Remove(x)); } /// @@ -412,20 +346,19 @@ private void HandleMissedHitObjects() { 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); - // Add a miss to the score. - ScoreProcessor.CalculateScore(stat); - - 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, true, false); + ScoreProcessor.CalculateScore(Judgement.Miss, true); ScoreProcessor.Stats.Add(stat); } @@ -436,33 +369,10 @@ private void HandleMissedHitObjects() break; } } - // Handle missed mines. - // 'Missed' as in the mines were not triggered, meaning a marvelous judgement should be given. - foreach (var hitObject in ActiveMines) - { - var endTime = hitObject.IsLongNote ? hitObject.EndTime : hitObject.StartTime; - if (Time > endTime + ScoreProcessor.JudgementWindow[Judgement.Marv]) - { - // Create a new HitStat to add to the ScoreProcessor. - // Award a Marvelous for successfully avoiding the mine. - var stat = new HitStat(HitStatType.Hit, KeyPressType.None, hitObject, hitObject.StartTime, Judgement.Marv, 0, - ScoreProcessor.Accuracy, ScoreProcessor.Health); - - ScoreProcessor.CalculateScore(stat); - - ScoreProcessor.Stats.Add(stat); - ActiveMinesToRemove.Add(hitObject); - } - else if (Time < hitObject.StartTime - ScoreProcessor.JudgementWindow[Judgement.Marv]) - { - break; - } - } // Remove all objects ActiveHitObjectsToRemove.ForEach(x => ActiveHitObjects.Remove(x)); ActiveHeldLongNotesToRemove.ForEach(x => ActiveHeldLongNotes.Remove(x)); - ActiveMinesToRemove.ForEach(x => ActiveMines.Remove(x)); } /// diff --git a/Quaver.Tools/Commands/RecalculateCommand.cs b/Quaver.Tools/Commands/RecalculateCommand.cs index 9379fef22..f27d110d9 100644 --- a/Quaver.Tools/Commands/RecalculateCommand.cs +++ b/Quaver.Tools/Commands/RecalculateCommand.cs @@ -63,22 +63,22 @@ private void Recalculate(JToken scores) var processor = new ScoreProcessorKeys(qua, 0); for (var i = 0; i < (int)score["count_marv"]; i++) - processor.CalculateScore(Judgement.Marv, false, false); + processor.CalculateScore(Judgement.Marv); for (var i = 0; i < (int)score["count_perf"]; i++) - processor.CalculateScore(Judgement.Perf, false, false); + processor.CalculateScore(Judgement.Perf); for (var i = 0; i < (int)score["count_great"]; i++) - processor.CalculateScore(Judgement.Great, false, false); + processor.CalculateScore(Judgement.Great); for (var i = 0; i < (int)score["count_good"]; i++) - processor.CalculateScore(Judgement.Good, false, false); + processor.CalculateScore(Judgement.Good); for (var i = 0; i < (int)score["count_okay"]; i++) - processor.CalculateScore(Judgement.Okay, false, false); + processor.CalculateScore(Judgement.Okay); for (var i = 0; i < (int)score["count_miss"]; i++) - processor.CalculateScore(Judgement.Miss, false, false); + processor.CalculateScore(Judgement.Miss); var difficultyRating = (double)score["performance_rating"] / Math.Pow((double)score["accuracy"] / 98, 6);