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(0.67f); private static readonly TimeSpan ROLL_DURATION = TimeSpan.FromSeconds(0.5f); private double fadeOut(double progress, double min, double max) => min + (max - min) * (1.0 - Math.Pow(1.0 - progress, 2.0)); private double fadeIn(double progress, double min, double max) => min + (max - min) * Math.Pow(progress, 2.0); private bool isHolding => Singleton.instance.getStateOn(UIInput.Key.MenuLeft) || Singleton.instance.getStateOn(UIInput.Key.MenuRight); private patch_NotesManager ntMgr => (patch_NotesManager)_gameEngine?.notesManager; private GameEngine _gameEngine; private SessionInfo _sessionInfo; private bool _isForceEndBattle; private bool _isRolling; private bool _isHoldingAck; private float _totalRollingFrame; private DateTime _rollingStartTime; 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(_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)) { startRolling(); } else { skipPlay(); } } orig_Execute_Play(); } else { _isHoldingAck = false; orig_Execute_Play(); } } private extern void orig_Execute_DispCombo(); private void Execute_DispCombo() { orig_Execute_DispCombo(); if(Singleton.instance.getStateOn(UIInput.Key.MenuRight) && ntMgr.retireResult != RetireResult.None && !isPartyPlay()) { startRolling(); endRolling(); _gameEngine.battleUI.skipDispRetireResult(); setNextState(EState.Play); } } private extern void orig_Execute_DispFinish(); private void Execute_DispFinish() { orig_Execute_DispFinish(); if(Singleton.instance.getStateOn(UIInput.Key.MenuRight) && ntMgr.retireResult != RetireResult.None && !isPartyPlay()) { ntMgr.stopPlay(); ntMgr.setPause(false); _gameEngine.reset(); Singleton.instance.gameBGM.stop(); setNextState(EState.Init); } } private void startRolling() { _isRolling = true; _totalRollingFrame = ntMgr.getCurrentFrame(); _rollingStartTime = CustomDateTime.Now; _enemyPosX = ntMgr.getEnemyPos().x; _gameEngine.destroyAllies(); ntMgr.forceRecover(recover: 100); Singleton.instance.gameBGM.stop(); } private void endRolling() { _isRolling = false; _isForceEndBattle = false; ntMgr.stopPlay(); ntMgr.setPause(false); ntMgr.reset(); // This has to go first or otherwise enemies will shrink _gameEngine.createPlayers(); _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 skipPlay() { Singleton.instance.SkipPlay = true; setNextState(EState.End); destroy(); ntMgr.stopPlay(); _gameEngine.destroyAllies(); _gameEngine.finishGame(); _gameEngine.playFinish(); } }