diff --git a/AquaMai/AquaMai.csproj b/AquaMai/AquaMai.csproj
index b5684bb3..428fd711 100644
--- a/AquaMai/AquaMai.csproj
+++ b/AquaMai/AquaMai.csproj
@@ -271,6 +271,7 @@
+
diff --git a/AquaMai/AquaMai.toml b/AquaMai/AquaMai.toml
index 287f97fd..6df4b43f 100644
--- a/AquaMai/AquaMai.toml
+++ b/AquaMai/AquaMai.toml
@@ -18,6 +18,8 @@ SkipToMusicSelection=false
CustomVersionString=""
# Load Jacket image from folder "LocalAssets" and filename "{MusicID}.png" for self-made charts
LoadJacketPng=true
+# Press key "7" for 1 second to skip to next step or restart current song
+QuickSkip=true
[Performance]
# Disable some useless checks and delays to speed up the game boot process
diff --git a/AquaMai/Config.cs b/AquaMai/Config.cs
index d49bd727..203b92eb 100644
--- a/AquaMai/Config.cs
+++ b/AquaMai/Config.cs
@@ -20,6 +20,7 @@ namespace AquaMai
public bool SinglePlayer { get; set; }
public bool SkipToMusicSelection { get; set; }
public bool LoadJacketPng { get; set; }
+ public bool QuickSkip { get; set; }
public string CustomVersionString { get; set; }
}
diff --git a/AquaMai/UX/QuickSkip.cs b/AquaMai/UX/QuickSkip.cs
new file mode 100644
index 00000000..0ac49674
--- /dev/null
+++ b/AquaMai/UX/QuickSkip.cs
@@ -0,0 +1,86 @@
+using System.Collections.Generic;
+using HarmonyLib;
+using Mai2.Mai2Cue;
+using MAI2.Util;
+using Main;
+using Manager;
+using MelonLoader;
+using Process;
+using Process.Information;
+using UnityEngine;
+
+namespace AquaMai.UX
+{
+ public class QuickSkip
+ {
+ private static ProcessDataContainer _container;
+ private static int _keyPressFrames;
+
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(ProcessDataContainer), MethodType.Constructor)]
+ public static void OnCreateProcessDataContainer(ProcessDataContainer __instance)
+ {
+ _container = __instance;
+ }
+
+ [HarmonyPrefix]
+ [HarmonyPatch(typeof(GameMainObject), "Update")]
+ public static void OnGameMainObjectUpdate()
+ {
+ // The button between [1p] and [2p] button on ADX
+ if (Input.GetKey(KeyCode.Alpha7)) _keyPressFrames++;
+
+ if (Input.GetKeyUp(KeyCode.Alpha7))
+ {
+ _keyPressFrames = 0;
+ MelonLogger.Msg(_container.processManager.Dump());
+ return;
+ }
+
+ if (_keyPressFrames != 60) return;
+
+ var traverse = Traverse.Create(_container.processManager);
+ var processList = traverse.Field("_processList").GetValue>();
+
+ var flagGoToMusicSelect = false;
+
+ foreach (ProcessManager.ProcessControle process in processList)
+ {
+ switch (process.Process.ToString())
+ {
+ // After login
+ case "Process.ModeSelect.ModeSelectProcess":
+ case "Process.RegionalSelectProcess":
+ case "Process.CharacterSelectProcess":
+ case "Process.TicketSelect.TicketSelectProcess":
+ // After playing a song
+ case "Process.ResultProcess":
+ case "Process.MapResultProcess":
+ _container.processManager.ReleaseProcess(process.Process);
+ flagGoToMusicSelect = true;
+ break;
+
+ case "Process.MusicSelectProcess":
+ // Skip to save
+ SoundManager.PreviewEnd();
+ SoundManager.PlayBGM(Cue.BGM_COLLECTION, 2);
+ _container.processManager.ReleaseProcess(process.Process);
+ _container.processManager.AddProcess(new UnlockMusicProcess(_container));
+ break;
+
+ case "Process.GameProcess":
+ // This is original typo in Assembly-CSharp
+ Singleton.Instance.SetQuickRetryFrag(flag: true);
+ break;
+ }
+ }
+
+ if (flagGoToMusicSelect)
+ {
+ GameManager.SetMaxTrack();
+ _container.processManager.AddProcess(new MusicSelectProcess(_container));
+ }
+ }
+
+ }
+}