diff --git a/Quaver.API/Enums/GameMode.cs b/Quaver.API/Enums/GameMode.cs
index 9a8a976b5..327d02076 100644
--- a/Quaver.API/Enums/GameMode.cs
+++ b/Quaver.API/Enums/GameMode.cs
@@ -16,6 +16,15 @@ namespace Quaver.API.Enums
public enum GameMode
{
Keys4 = 1,
- Keys7 = 2
+ Keys7 = 2,
+
+ Keys1 = 3,
+ Keys2 = 4,
+ Keys3 = 5,
+ Keys5 = 6,
+ Keys6 = 7,
+ Keys8 = 8,
+ Keys9 = 9,
+ Keys10 = 10,
}
}
diff --git a/Quaver.API/Helpers/ModeHelper.cs b/Quaver.API/Helpers/ModeHelper.cs
index 1f73fefef..22ceebce9 100644
--- a/Quaver.API/Helpers/ModeHelper.cs
+++ b/Quaver.API/Helpers/ModeHelper.cs
@@ -12,6 +12,8 @@ namespace Quaver.API.Helpers
{
public static class ModeHelper
{
+ public static int MaxKeyCount => Enum.GetValues(typeof(GameMode)).Length;
+
///
/// Converts game mode to short hand version.
///
@@ -21,19 +23,25 @@ public static class ModeHelper
///
public static string ToShortHand(GameMode mode, bool hasScratch = false)
{
+ string res;
switch (mode)
{
- case GameMode.Keys4:
- if (hasScratch)
- return "4K+1";
- return "4K";
- case GameMode.Keys7:
- if (hasScratch)
- return "7K+1";
- return "7K";
+ case GameMode.Keys4: res = "4K"; break;
+ case GameMode.Keys7: res = "7K"; break;
+
+ case GameMode.Keys1: res = "1K"; break;
+ case GameMode.Keys2: res = "2K"; break;
+ case GameMode.Keys3: res = "3K"; break;
+ case GameMode.Keys5: res = "5K"; break;
+ case GameMode.Keys6: res = "6K"; break;
+ case GameMode.Keys8: res = "8K"; break;
+ case GameMode.Keys9: res = "9K"; break;
+ case GameMode.Keys10: res = "10K"; break;
default:
throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
}
+
+ return res + (hasScratch ? "+1" : "");
}
///
@@ -46,13 +54,69 @@ public static string ToLongHand(GameMode mode)
{
switch (mode)
{
- case GameMode.Keys4:
- return "4 Keys";
- case GameMode.Keys7:
- return "7 Keys";
+ case GameMode.Keys4: return "4 Keys";
+ case GameMode.Keys7: return "7 Keys";
+
+ case GameMode.Keys1: return "1 Keys";
+ case GameMode.Keys2: return "2 Keys";
+ case GameMode.Keys3: return "3 Keys";
+ case GameMode.Keys5: return "5 Keys";
+ case GameMode.Keys6: return "6 Keys";
+ case GameMode.Keys8: return "8 Keys";
+ case GameMode.Keys9: return "9 Keys";
+ case GameMode.Keys10: return "10 Keys";
+ default:
+ throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
+ }
+ }
+
+ public static int ToKeyCount(GameMode mode, bool hasScratch = false)
+ {
+ int res;
+ switch (mode)
+ {
+
+ case GameMode.Keys4: res = 4; break;
+ case GameMode.Keys7: res = 7; break;
+
+ case GameMode.Keys1: res = 1; break;
+ case GameMode.Keys2: res = 2; break;
+ case GameMode.Keys3: res = 3; break;
+ case GameMode.Keys5: res = 5; break;
+ case GameMode.Keys6: res = 6; break;
+ case GameMode.Keys8: res = 8; break;
+ case GameMode.Keys9: res = 9; break;
+ case GameMode.Keys10: res = 10; break;
default:
throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
}
+
+ return res + (hasScratch ? 1 : 0);
+ }
+
+ public static GameMode FromKeyCount(int keyCount)
+ {
+ switch (keyCount)
+ {
+ case 4: return GameMode.Keys4;
+ case 7: return GameMode.Keys7;
+
+ case 1: return GameMode.Keys1;
+ case 2: return GameMode.Keys2;
+ case 3: return GameMode.Keys3;
+ case 5: return GameMode.Keys5;
+ case 6: return GameMode.Keys6;
+ case 8: return GameMode.Keys8;
+ case 9: return GameMode.Keys9;
+ case 10: return GameMode.Keys10;
+ default: throw new ArgumentOutOfRangeException(nameof(keyCount), keyCount, null);
+ }
+ }
+
+ public static bool IsKeyMode(GameMode mode)
+ {
+ // we only have keys gamemode for now...
+ return true;
}
}
}
diff --git a/Quaver.API/Maps/Parsers/Malody/MalodyFile.cs b/Quaver.API/Maps/Parsers/Malody/MalodyFile.cs
index 1944e96ce..1fd54100e 100644
--- a/Quaver.API/Maps/Parsers/Malody/MalodyFile.cs
+++ b/Quaver.API/Maps/Parsers/Malody/MalodyFile.cs
@@ -1,5 +1,6 @@
using Newtonsoft.Json;
using Quaver.API.Enums;
+using Quaver.API.Helpers;
using Quaver.API.Maps.Structures;
using System;
using System.Collections.Generic;
@@ -57,17 +58,7 @@ public Qua ToQua()
if (Meta.Mode != 0)
throw new ArgumentException("Only the 'Key' Malody game mode can be converted to Qua");
- switch (Meta.Keymode.Keymode)
- {
- case 4:
- qua.Mode = GameMode.Keys4;
- break;
- case 7:
- qua.Mode = GameMode.Keys7;
- break;
- default:
- throw new InvalidEnumArgumentException();
- }
+ qua.Mode = ModeHelper.FromKeyCount(Meta.Keymode.Keymode);
foreach (var tp in TimingPoints)
{
diff --git a/Quaver.API/Maps/Parsers/OsuBeatmap.cs b/Quaver.API/Maps/Parsers/OsuBeatmap.cs
index 4cc6201bc..a864afdc9 100644
--- a/Quaver.API/Maps/Parsers/OsuBeatmap.cs
+++ b/Quaver.API/Maps/Parsers/OsuBeatmap.cs
@@ -293,7 +293,7 @@ public OsuBeatmap(string filePath)
case "CircleSize":
KeyCount = int.Parse(value, CultureInfo.InvariantCulture);
- if (KeyCount != 4 && KeyCount != 7 && KeyCount != 5 && KeyCount != 8)
+ if (KeyCount < 1 || KeyCount > ModeHelper.MaxKeyCount)
IsValid = false;
break;
case "OverallDifficulty":
@@ -476,27 +476,10 @@ public Qua ToQua(bool checkValidity = true)
Tags = Tags,
Creator = Creator,
DifficultyName = Version,
- Description = $"This is a Quaver converted version of {Creator}'s map."
+ Description = $"This is a Quaver converted version of {Creator}'s map.",
+ Mode = ModeHelper.FromKeyCount(KeyCount)
};
- // Get the correct game mode based on the amount of keys the map has.
- switch (KeyCount)
- {
- case 4:
- qua.Mode = GameMode.Keys4;
- break;
- case 7:
- qua.Mode = GameMode.Keys7;
- break;
- case 8:
- qua.Mode = GameMode.Keys7;
- qua.HasScratchKey = true;
- break;
- default:
- qua.Mode = (GameMode)(-1);
- break;
- }
-
foreach (var path in CustomAudioSamples)
{
qua.CustomAudioSamples.Add(new CustomAudioSampleInfo()
diff --git a/Quaver.API/Maps/Processors/Difficulty/Rulesets/Keys/DifficultyProcessorKeys.cs b/Quaver.API/Maps/Processors/Difficulty/Rulesets/Keys/DifficultyProcessorKeys.cs
index 349ef6488..021e4918a 100644
--- a/Quaver.API/Maps/Processors/Difficulty/Rulesets/Keys/DifficultyProcessorKeys.cs
+++ b/Quaver.API/Maps/Processors/Difficulty/Rulesets/Keys/DifficultyProcessorKeys.cs
@@ -46,52 +46,72 @@ public class DifficultyProcessorKeys : DifficultyProcessor
///
/// Assumes that the assigned hand will be the one to press that key
///
- private Dictionary LaneToHand4K { get; set; } = new Dictionary()
+ private static Hand LaneToHand(int lane, int keyCount)
{
- {1, Hand.Left},
- {2, Hand.Left},
- {3, Hand.Right},
- {4, Hand.Right}
- };
+ if (lane < 1 || lane > keyCount)
+ throw new ArgumentOutOfRangeException(nameof(lane), "Lane must be between 1 and keyCount");
- ///
- /// Assumes that the assigned hand will be the one to press that key
- ///
- private Dictionary LaneToHand7K { get; set; } = new Dictionary()
- {
- {1, Hand.Left},
- {2, Hand.Left},
- {3, Hand.Left},
- {4, Hand.Ambiguous},
- {5, Hand.Right},
- {6, Hand.Right},
- {7, Hand.Right}
- };
+ var half = keyCount / 2;
- ///
- /// Assumes that the assigned finger will be the one to press that key.
- ///
- private Dictionary LaneToFinger4K { get; set; } = new Dictionary()
- {
- {1, FingerState.Middle},
- {2, FingerState.Index},
- {3, FingerState.Index},
- {4, FingerState.Middle}
- };
+ if (keyCount % 2 == 0)
+ {
+ if (lane <= half)
+ return Hand.Left;
+ else
+ return Hand.Right;
+ }
+ else
+ {
+ if (lane <= half)
+ return Hand.Left;
+
+ if (lane == half + 1)
+ return Hand.Ambiguous;
+ else
+ return Hand.Right;
+ }
+ }
///
/// Assumes that the assigned finger will be the one to press that key.
///
- private Dictionary LaneToFinger7K { get; set; } = new Dictionary()
+ private static FingerState LaneToFinger(int lane, int keyCount)
{
- {1, FingerState.Ring},
- {2, FingerState.Middle},
- {3, FingerState.Index},
- {4, FingerState.Thumb},
- {5, FingerState.Index},
- {6, FingerState.Middle},
- {7, FingerState.Ring}
- };
+ if (lane < 1 || lane > keyCount)
+ throw new ArgumentOutOfRangeException(nameof(lane), "Lane must be between 1 and keyCount");
+
+ var half = keyCount / 2;
+
+ if (keyCount <= 9)
+ {
+ // even key count
+ if (keyCount % 2 == 0)
+ {
+ if (lane <= half)
+ return (FingerState)(1 << (half - lane));
+ else
+ return (FingerState)(1 << (lane - (half + 1)));
+ }
+
+ // odd key count
+ if (lane <= half)
+ return (FingerState)(1 << (half - lane));
+ if (lane == half + 1)
+ return FingerState.Thumb;
+ return (FingerState)(1 << (lane - (half + 2)));
+ }
+
+ if (keyCount == 10)
+ {
+ if (lane <= half - 1)
+ return (FingerState)(1 << (half - 1 - lane));
+ if (lane == half || lane == half + 1)
+ return FingerState.Thumb;
+ return (FingerState)(1 << (lane - (half + 2)));
+ }
+
+ throw new ArgumentOutOfRangeException(nameof(keyCount), "Key count must be between 1 and 10");
+ }
///
/// Value of confidence that there's vibro manipulation in the calculated map.
@@ -114,7 +134,7 @@ public DifficultyProcessorKeys(Qua map, StrainConstants constants, ModIdentifier
bool detailedSolve = false) : base(map, constants, mods)
{
// Cast the current Strain Constants Property to the correct type.
- StrainConstants = (StrainConstantsKeys) constants;
+ StrainConstants = (StrainConstantsKeys)constants;
// Don't bother calculating map difficulty if there's less than 2 hit objects
if (map.HitObjects.Count < 2)
@@ -144,15 +164,10 @@ public void CalculateDifficulty(ModIdentifier mods)
var rate = ModHelper.GetRateFromMods(mods);
// Compute for overall difficulty
- switch (Map.Mode)
- {
- case GameMode.Keys4:
- OverallDifficulty = ComputeForOverallDifficulty(rate);
- break;
- case GameMode.Keys7:
- OverallDifficulty = (ComputeForOverallDifficulty(rate, Hand.Left) + ComputeForOverallDifficulty(rate, Hand.Right) ) / 2;
- break;
- }
+ if (ModeHelper.ToKeyCount(Map.Mode) % 2 == 0)
+ OverallDifficulty = ComputeForOverallDifficulty(rate);
+ else
+ OverallDifficulty = (ComputeForOverallDifficulty(rate, Hand.Left) + ComputeForOverallDifficulty(rate, Hand.Right)) / 2;
}
///
@@ -193,19 +208,12 @@ private void ComputeBaseStrainStates(float rate, Hand assumeHand)
var curStrainData = new StrainSolverData(curHitOb, rate);
// Assign Finger and Hand States
- switch (Map.Mode)
- {
- case GameMode.Keys4:
- curHitOb.FingerState = LaneToFinger4K[Map.HitObjects[i].Lane];
- curStrainData.Hand = LaneToHand4K[Map.HitObjects[i].Lane];
- break;
- case GameMode.Keys7:
- curHitOb.FingerState = LaneToFinger7K[Map.HitObjects[i].Lane];
- curStrainData.Hand = LaneToHand7K[Map.HitObjects[i].Lane] == Hand.Ambiguous
- ? assumeHand
- : LaneToHand7K[Map.HitObjects[i].Lane];
- break;
- }
+ var keyCount = ModeHelper.ToKeyCount(Map.Mode);
+
+ curHitOb.FingerState = LaneToFinger(Map.HitObjects[i].Lane, keyCount);
+
+ var hand = LaneToHand(Map.HitObjects[i].Lane, keyCount);
+ curStrainData.Hand = hand == Hand.Ambiguous ? assumeHand : hand;
// Add Strain Solver Data to list
StrainSolverData.Add(curStrainData);
@@ -283,7 +291,7 @@ private void ComputeForFingerActions()
if (curHitOb.Hand == nextHitOb.Hand && nextHitOb.StartTime > curHitOb.StartTime)
{
// Determined by if there's a minijack within 2 set of chords/single notes
- var actionJackFound = ( curHitOb.FingerState & nextHitOb.FingerState ) != 0;
+ var actionJackFound = (curHitOb.FingerState & nextHitOb.FingerState) != 0;
// Determined by if a chord is found in either finger state
var actionChordFound = curHitOb.HandChord || nextHitOb.HandChord;
@@ -437,7 +445,7 @@ private void ComputeForJackManipulation()
// 93.7ms = 160bpm 1/4 vibro
// 35f = 35ms tolerance before hitting vibro point (88.2ms, 170bpm vibro)
- var durationValue = Math.Min(1, Math.Max(0, (StrainConstants.VibroActionDurationMs + StrainConstants.VibroActionToleranceMs - data.FingerActionDurationMs ) / StrainConstants.VibroActionToleranceMs));
+ var durationValue = Math.Min(1, Math.Max(0, (StrainConstants.VibroActionDurationMs + StrainConstants.VibroActionToleranceMs - data.FingerActionDurationMs) / StrainConstants.VibroActionToleranceMs));
var durationMultiplier = 1 - durationValue * (1 - StrainConstants.VibroMultiplier);
var manipulationFoundRatio = 1 - longJackSize / StrainConstants.VibroMaxLength * (1 - StrainConstants.VibroLengthMultiplier);
@@ -479,7 +487,7 @@ private void ComputeForLnMultiplier()
if (next != null)
{
- // Check to see if the target hitobject is layered inside the current LN
+ // Check to see if the target hitobject is layered inside the current LN
if (next.StartTime < data.EndTime - StrainConstants.LnEndThresholdMs)
{
if (next.StartTime >= data.StartTime + StrainConstants.LnEndThresholdMs)
@@ -614,7 +622,7 @@ private float CalculateOverallDifficulty()
// We do not consider sections without notes, since there are no "easy notes". Those sections have barely
// affected the rating in the old difficulty calculator.
- var continuity = (float) bins.Where(strain => strain > 0)
+ var continuity = (float)bins.Where(strain => strain > 0)
.Average(strain => Math.Sqrt(strain / easyRatingCutoff));
// The average continuity of maps in our dataset has been observed to be around 0.85, so we take that
@@ -631,13 +639,13 @@ private float CalculateOverallDifficulty()
if (continuity > avgContinuity)
{
- var continuityFactor = 1 - (continuity - avgContinuity)/(maxContinuity - avgContinuity);
- continuityAdjustment = Math.Min(avgAdjustment, Math.Max(minAdjustment, continuityFactor * ( avgAdjustment - minAdjustment ) + minAdjustment
+ var continuityFactor = 1 - (continuity - avgContinuity) / (maxContinuity - avgContinuity);
+ continuityAdjustment = Math.Min(avgAdjustment, Math.Max(minAdjustment, continuityFactor * (avgAdjustment - minAdjustment) + minAdjustment
));
}
else
{
- var continuityFactor = 1 - (continuity - minContinuity)/(avgContinuity - minContinuity);
+ var continuityFactor = 1 - (continuity - minContinuity) / (avgContinuity - minContinuity);
continuityAdjustment = Math.Min(maxAdjustment, Math.Max(avgAdjustment, continuityFactor * (maxAdjustment - avgAdjustment) + avgAdjustment));
}
@@ -667,7 +675,7 @@ private float CalculateOverallDifficulty()
private void ComputeNoteDensityData(float rate)
{
//MapLength = Qua.Length;
- AverageNoteDensity = SECONDS_TO_MILLISECONDS * Map.HitObjects.Count / ( Map.Length * ( -.5f * rate + 1.5f ) );
+ AverageNoteDensity = SECONDS_TO_MILLISECONDS * Map.HitObjects.Count / (Map.Length * (-.5f * rate + 1.5f));
}
///
@@ -695,7 +703,7 @@ private float GetCoefficientValue(float duration, float xMin, float xMax, float
}
// compute for difficulty
- return lowestDifficulty + (strainMax - lowestDifficulty) * (float) Math.Pow(ratio, exp);
+ return lowestDifficulty + (strainMax - lowestDifficulty) * (float)Math.Pow(ratio, exp);
}
}
}
\ No newline at end of file
diff --git a/Quaver.API/Maps/Qua.cs b/Quaver.API/Maps/Qua.cs
index e6e955fae..e51b41e68 100644
--- a/Quaver.API/Maps/Qua.cs
+++ b/Quaver.API/Maps/Qua.cs
@@ -571,14 +571,7 @@ public float GetActionsPerSecond(float rate = 1.0f)
/// This translates mode to key count.
///
///
- public int GetKeyCount(bool includeScratch = true) =>
- Mode switch
- {
- GameMode.Keys4 => 4,
- GameMode.Keys7 => 7,
- _ => throw new InvalidEnumArgumentException(),
- } +
- (HasScratchKey && includeScratch ? 1 : 0);
+ public int GetKeyCount(bool includeScratch = true) => ModeHelper.ToKeyCount(Mode, HasScratchKey && includeScratch);
///
/// Finds the most common BPM in a Qua object.
@@ -725,12 +718,10 @@ public DifficultyProcessor SolveDifficulty(ModIdentifier mods = ModIdentifier.No
qua.ApplyMods(mods);
}
- return Mode switch
- {
- GameMode.Keys4 => new DifficultyProcessorKeys(qua, new StrainConstantsKeys(), mods),
- GameMode.Keys7 => new DifficultyProcessorKeys(qua, new StrainConstantsKeys(), mods),
- _ => throw new InvalidEnumArgumentException(),
- };
+ if (ModeHelper.IsKeyMode(qua.Mode))
+ return new DifficultyProcessorKeys(qua, new StrainConstantsKeys(), mods);
+ else
+ throw new InvalidEnumArgumentException();
}
///
diff --git a/Quaver.API/Replays/Replay.cs b/Quaver.API/Replays/Replay.cs
index d0af0977c..3458e0d39 100644
--- a/Quaver.API/Replays/Replay.cs
+++ b/Quaver.API/Replays/Replay.cs
@@ -383,32 +383,7 @@ public static Replay GeneratePerfectReplayKeys(Replay replay, Qua map)
///
///
///
- public static ReplayKeyPressState KeyLaneToPressState(int lane)
- {
- switch (lane)
- {
- case 1:
- return ReplayKeyPressState.K1;
- case 2:
- return ReplayKeyPressState.K2;
- case 3:
- return ReplayKeyPressState.K3;
- case 4:
- return ReplayKeyPressState.K4;
- case 5:
- return ReplayKeyPressState.K5;
- case 6:
- return ReplayKeyPressState.K6;
- case 7:
- return ReplayKeyPressState.K7;
- case 8:
- return ReplayKeyPressState.K8;
- case 9:
- return ReplayKeyPressState.K9;
- default:
- throw new ArgumentException("Lane specified must be between 1 and 7");
- }
- }
+ public static ReplayKeyPressState KeyLaneToPressState(int lane) => (ReplayKeyPressState)(1 << (lane - 1));
///
/// Converts a key press state to a list of lanes that are active.
@@ -419,24 +394,12 @@ public static List KeyPressStateToLanes(ReplayKeyPressState keys)
{
var lanes = new List();
- if (keys.HasFlag(ReplayKeyPressState.K1))
- lanes.Add(0);
- if (keys.HasFlag(ReplayKeyPressState.K2))
- lanes.Add(1);
- if (keys.HasFlag(ReplayKeyPressState.K3))
- lanes.Add(2);
- if (keys.HasFlag(ReplayKeyPressState.K4))
- lanes.Add(3);
- if (keys.HasFlag(ReplayKeyPressState.K5))
- lanes.Add(4);
- if (keys.HasFlag(ReplayKeyPressState.K6))
- lanes.Add(5);
- if (keys.HasFlag(ReplayKeyPressState.K7))
- lanes.Add(6);
- if (keys.HasFlag(ReplayKeyPressState.K8))
- lanes.Add(7);
- if (keys.HasFlag(ReplayKeyPressState.K9))
- lanes.Add(8);
+ // MaxKeyCount + 2 to include the 2 keys used for scratch
+ for (var i = 0; i < ModeHelper.MaxKeyCount + 2; i++)
+ {
+ if (keys.HasFlag((ReplayKeyPressState)(1 << i)))
+ lanes.Add(i);
+ }
return lanes;
}
diff --git a/Quaver.API/Replays/ReplayKeyPressState.cs b/Quaver.API/Replays/ReplayKeyPressState.cs
index b11ebf5bd..ed7fa1a0b 100644
--- a/Quaver.API/Replays/ReplayKeyPressState.cs
+++ b/Quaver.API/Replays/ReplayKeyPressState.cs
@@ -23,6 +23,10 @@ public enum ReplayKeyPressState
K6 = 1 << 5,
K7 = 1 << 6,
K8 = 1 << 7,
- K9 = 1 << 8 // Scratch Lane Second Key on 7K+1
+ K9 = 1 << 8,
+ K10 = 1 << 9,
+ K11 = 1 << 10,
+ K12 = 1 << 11,
+
}
}
diff --git a/Quaver.API/Replays/Virtual/VirtualReplayPlayer.cs b/Quaver.API/Replays/Virtual/VirtualReplayPlayer.cs
index ee055a6d9..8b86668ca 100644
--- a/Quaver.API/Replays/Virtual/VirtualReplayPlayer.cs
+++ b/Quaver.API/Replays/Virtual/VirtualReplayPlayer.cs
@@ -9,6 +9,7 @@
using System.Collections.Generic;
using System.Linq;
using Quaver.API.Enums;
+using Quaver.API.Helpers;
using Quaver.API.Maps;
using Quaver.API.Maps.Processors.Scoring;
using Quaver.API.Maps.Processors.Scoring.Data;
@@ -99,35 +100,13 @@ public VirtualReplayPlayer(Replay replay, Qua map, JudgementWindows windows = nu
map.HitObjects.ForEach(x => ActiveHitObjects.Add(x));
// Add virtual key bindings based on the game mode of the replay.
- switch (Map.Mode)
- {
- case GameMode.Keys4:
- InputKeyStore = new List()
- {
- new VirtualReplayKeyBinding(ReplayKeyPressState.K1),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K2),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K3),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K4),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K5),
- };
- break;
- case GameMode.Keys7:
- InputKeyStore = new List()
- {
- new VirtualReplayKeyBinding(ReplayKeyPressState.K1),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K2),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K3),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K4),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K5),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K6),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K7),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K8),
- new VirtualReplayKeyBinding(ReplayKeyPressState.K9),
- };
- break;
- default:
- throw new ArgumentOutOfRangeException();
- }
+ InputKeyStore = new List();
+ var keyCount = ModeHelper.ToKeyCount(map.Mode);
+ if (map.HasScratchKey)
+ keyCount += 2; // Scratch can be pressed by 2 keys
+
+ for (var i = 0; i < keyCount; i++)
+ InputKeyStore.Add(new VirtualReplayKeyBinding((ReplayKeyPressState)(1 << i)));
}
///
@@ -222,8 +201,8 @@ private void HandleKeyPressesInFrame()
{
var inputLane = key;
- // Allow scratch key to be dual-binded to lane 8
- if (Map.HasScratchKey && Map.Mode == GameMode.Keys7 && key + 1 == 9)
+ // Allow scratch key to be dual-binded
+ if (Map.HasScratchKey && key + 1 == ModeHelper.ToKeyCount(Map.Mode) + 2)
inputLane--;
// This key was uniquely pressed during this frame.