using MonoMod; using MU3.Battle; using MU3.Game; using MU3.Notes; using MU3.Util; using System; using UnityEngine; namespace MU3.Sequence; class patch_PlayMusic: PlayMusic { private static readonly TimeSpan HOLD_DURATION = TimeSpan.FromSeconds(1.0f); private static readonly TimeSpan ROLL_DURATION = TimeSpan.FromSeconds(0.5f); private GameEngine _gameEngine; private SessionInfo _sessionInfo; private patch_NotesManager ntMgr => (patch_NotesManager)_gameEngine?.notesManager; private bool _pressedYellow; private bool _isRolling; private float _totalRollingFrame; private DateTime _rollingStartTime; private bool _isHoldingAck; private DateTime _holdingStartTime; private float _enemyPosX; [MonoModIgnore] private extern bool isPartyPlay(); private extern void orig_Execute_Play(); private void Execute_Play() { if(isPartyPlay() || _sessionInfo.isTutorial) { orig_Execute_Play(); return; } if(Singleton.instance.getTriggerOn(UIInput.Key.MenuRight)) { _pressedYellow = true; } if(_isRolling) { TimeSpan timeSpan = CustomDateTime.Now - _rollingStartTime; if(timeSpan <= ROLL_DURATION) { double num1 = fadeOut(timeSpan.TotalMilliseconds / ROLL_DURATION.TotalMilliseconds, 0.0, 1.0); double num2 = fadeIn(timeSpan.TotalMilliseconds / ROLL_DURATION.TotalMilliseconds, 0.0, 1.0); ntMgr.setFrameForce(_totalRollingFrame * (float)(1.0 - num1)); ntMgr.enemyOffset = new Vector3( ntMgr.enemyOffset.x + (_enemyPosX - ntMgr.getEnemyPos().x), 20f * (float)num2, 0.0f ); } else { endRolling(); } } else if(isHolding()) { if(!_isHoldingAck) { _holdingStartTime = CustomDateTime.Now; _isHoldingAck = true; } TimeSpan ts = CustomDateTime.Now - _holdingStartTime; if(ts > HOLD_DURATION) { if(Singleton.instance.getStateOn(UIInput.Key.MenuRight)) { if(ntMgr.retireResult != RetireResult.None) { hardReset(); } else { startRolling(); } } else { Singleton.instance.SkipPlay = true; setNextState(EState.End); destroy(); ntMgr.stopPlay(); _gameEngine.destroyAllies(); _gameEngine.finishGame(); _gameEngine.playFinish(); } } } else { _isHoldingAck = false; orig_Execute_Play(); } } private static double fadeOut(double progress, double min, double max) { return min + (max - min) * (1.0 - Math.Pow(1.0 - progress, 2.0)); } private static double fadeIn(double progress, double min, double max) { return min + (max - min) * Math.Pow(progress, 2.0); } private bool isHolding() { return Singleton.instance.getStateOn(UIInput.Key.MenuLeft) ^ (_pressedYellow && Singleton.instance.getStateOn(UIInput.Key.MenuRight)); } private void hardReset() { ntMgr.stopPlay(); ntMgr.setPause(false); _gameEngine.reset(); Singleton.instance.gameBGM.stop(); setNextState(EState.Init); } private void startRolling() { _pressedYellow = false; _isRolling = true; _totalRollingFrame = ntMgr.getCurrentFrame(); _rollingStartTime = CustomDateTime.Now; _enemyPosX = ntMgr.getEnemyPos().x; ntMgr.forceRecover(recover: 100); Singleton.instance.gameBGM.stop(); } private void endRolling() { _isRolling = false; ntMgr.stopPlay(); ntMgr.setPause(false); ntMgr.reset(); _gameEngine.counters.reset(); _gameEngine.enemyManager.destroy(); ntMgr.reloadScore(_gameEngine.IsStageDazzling); _gameEngine.battleReward.initialize(_sessionInfo); _gameEngine.enemyManager.initialize(); _gameEngine.reset(); ntMgr.startPlay(0.0f); ntMgr.led.setGameColor(true); Singleton.instance.gameBGM.playMusic(_sessionInfo.musicData, 0); } private void listenForPanicRestart() { if(Singleton.instance.getTriggerOn(UIInput.Key.MenuRight) && ntMgr.retireResult != RetireResult.None && !isPartyPlay()) { hardReset(); } } private extern void orig_Execute_DispCombo(); private void Execute_DispCombo() { orig_Execute_DispCombo(); listenForPanicRestart(); } private extern void orig_Execute_DispFinish(); private void Execute_DispFinish() { orig_Execute_DispFinish(); listenForPanicRestart(); } }