@@ -36,13 +36,33 @@ public class PracticeMode
3636 [ ConfigEntry ]
3737 public static readonly bool longPress = false ;
3838
39+ [ ConfigEntry (
40+ name : "仅自由模式可用" ,
41+ en : "Only allow Practice Mode in Freedom Mode while time remains." ,
42+ zh : "仅在自由模式且时间未耗尽时允许使用练习模式" ) ]
43+ public static readonly bool onlyInFreedomMode = false ;
44+
3945 public static double repeatStart = - 1 ;
4046 public static double repeatEnd = - 1 ;
4147 public static float speed = 1 ;
4248 private static CriAtomExPlayer player ;
4349 private static List < MovieMaterialMai2 > movie ;
4450 private static GameCtrl [ ] gameCtrl = new GameCtrl [ 2 ] ;
4551 public static bool keepNoteSpeed = false ;
52+
53+ private static void ClearPracticeEffects ( )
54+ {
55+ // 清除练习模式的所有效果。涉及的效果有五种:UI界面、循环、速度保持、速度、暂停。
56+ if ( ui != null )
57+ {
58+ UnityEngine . Object . Destroy ( ui ) ;
59+ ui = null ;
60+ }
61+ if ( repeatStart >= 0 || repeatEnd >= 0 ) ClearRepeat ( ) ;
62+ keepNoteSpeed = false ;
63+ if ( speed != 1f ) SpeedReset ( ) ;
64+ if ( DebugFeature . Pause ) TogglePause ( ) ;
65+ }
4666
4767 public static void SetRepeatEnd ( double time )
4868 {
@@ -67,6 +87,15 @@ public static void ClearRepeat()
6787 repeatEnd = - 1 ;
6888 }
6989
90+ public static void TogglePause ( )
91+ {
92+ DebugFeature . Pause = ! DebugFeature . Pause ;
93+ if ( ! DebugFeature . Pause )
94+ {
95+ Seek ( 0 ) ;
96+ }
97+ }
98+
7099 public static void GameCtrlResetOptionSpeed ( )
71100 {
72101 foreach ( var g in gameCtrl )
@@ -169,6 +198,8 @@ public static double CurrentPlayMsec
169198
170199 public static PracticeModeUI ui ;
171200
201+ private static long prevFreedomModeMSec = - 1 ; // 上一帧时,自由模式的剩余秒数
202+
172203 [ HarmonyPatch ]
173204 public class PatchNoteSpeed
174205 {
@@ -192,7 +223,9 @@ public static void GameProcessPostStart()
192223 repeatStart = - 1 ;
193224 repeatEnd = - 1 ;
194225 speed = 1 ;
226+ keepNoteSpeed = false ;
195227 ui = null ;
228+ prevFreedomModeMSec = GameManager . IsFreedomMode ? GameManager . GetFreedomModeMSec ( ) : - 1 ;
196229 }
197230
198231 [ HarmonyPatch ( typeof ( GameProcess ) , "OnRelease" ) ]
@@ -202,7 +235,9 @@ public static void GameProcessPostRelease()
202235 repeatStart = - 1 ;
203236 repeatEnd = - 1 ;
204237 speed = 1 ;
238+ keepNoteSpeed = false ;
205239 ui = null ;
240+ prevFreedomModeMSec = - 1 ;
206241 }
207242
208243 [ HarmonyPatch ( typeof ( GameCtrl ) , "Initialize" ) ]
@@ -228,10 +263,19 @@ public static void OnGenericProcessUpdate(GenericMonitor[] ____monitors)
228263 [ HarmonyPostfix ]
229264 public static void GameProcessPostUpdate ( GameProcess __instance , GameMonitor [ ] ____monitors )
230265 {
231- if ( KeyListener . GetKeyDownOrLongPress ( key , longPress ) && ui is null )
266+ if ( KeyListener . GetKeyDownOrLongPress ( key , longPress ) && ui is null &&
267+ ( ! onlyInFreedomMode || ( GameManager . IsFreedomMode && GameManager . GetFreedomModeMSec ( ) > 0 ) ) ) // onlyInFreedomMode=true情况,则额外检查是否在练习模式内、且时间有剩余,如果不满足则不开启UI。
232268 {
233269 ui = ____monitors [ 0 ] . gameObject . AddComponent < PracticeModeUI > ( ) ;
234270 }
271+
272+ if ( onlyInFreedomMode && GameManager . IsFreedomMode )
273+ {
274+ var currentFreedomModeMSec = GameManager . GetFreedomModeMSec ( ) ;
275+ if ( prevFreedomModeMSec > 0 && currentFreedomModeMSec <= 0 )
276+ ClearPracticeEffects ( ) ; // 如果这一帧内、练习模式的时间刚好归零了:则清空练习模式的一切效果。
277+ prevFreedomModeMSec = currentFreedomModeMSec ;
278+ }
235279
236280 if ( repeatStart >= 0 && repeatEnd >= 0 )
237281 {
0 commit comments