1
0
forked from akanyan/mu3-mods
Files
mu3-mods/Enhancements/BetterGiveUp/MU3.Sequence/patch_PlayMusic.cs
2025-01-12 00:00:49 +00:00

169 lines
5.5 KiB
C#

using MonoMod;
using MU3.Battle;
using MU3.Game;
using MU3.Notes;
using MU3.Util;
using System;
using System.Collections;
using System.Reflection;
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);
[MonoModIgnore]
private patch_NotesManager ntMgr => null;
private GameEngine _gameEngine;
private SessionInfo _sessionInfo;
private bool _isForceEndBattle;
private bool _isRolling;
private bool _isHoldingAck;
private DateTime _holdingStartTime;
[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) {
return;
}
if(Singleton<UIInput>.instance.getTriggerOn(UIInput.Key.MenuLeft) || Singleton<UIInput>.instance.getTriggerOn(UIInput.Key.MenuRight)) {
_holdingStartTime = CustomDateTime.Now;
_isHoldingAck = true;
}
if(_isHoldingAck && (Singleton<UIInput>.instance.getStateOn(UIInput.Key.MenuLeft) || Singleton<UIInput>.instance.getStateOn(UIInput.Key.MenuRight))) {
if(CustomDateTime.Now - _holdingStartTime > HOLD_DURATION) {
if(Singleton<UIInput>.instance.getStateOn(UIInput.Key.MenuRight)) {
restartPlay(shouldRoll: true);
} else {
skipPlay();
}
}
} else {
_isHoldingAck = false;
}
orig_Execute_Play();
}
private extern void orig_Execute_DispCombo();
private void Execute_DispCombo() {
orig_Execute_DispCombo();
if(Singleton<UIInput>.instance.getStateOn(UIInput.Key.MenuRight) && ntMgr.retireResult != RetireResult.None && !isPartyPlay()) {
restartPlay(shouldRoll: false);
_gameEngine.battleUI.skipDispRetireResult();
setNextState(EState.Play);
}
}
private extern void orig_Execute_DispFinish();
private void Execute_DispFinish() {
orig_Execute_DispFinish();
if(Singleton<UIInput>.instance.getStateOn(UIInput.Key.MenuRight) && ntMgr.retireResult != RetireResult.None && !isPartyPlay()) {
ntMgr.stopPlay();
ntMgr.setPause(false);
_gameEngine.reset();
Singleton<GameSound>.instance.gameBGM.stop();
setNextState(EState.Init);
}
}
private void restartPlay(bool shouldRoll) {
_isHoldingAck = false;
_gameEngine.destroyAllies();
ntMgr.forceRecover(recover: 100);
Singleton<GameSound>.instance.gameBGM.stop();
if(shouldRoll) {
_isRolling = true;
_gameEngine.StartCoroutine(roll());
} else {
finishRestart();
}
}
private void finishRestart() {
_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<GameSound>.instance.gameBGM.playMusic(_sessionInfo.musicData, 0);
}
private IEnumerator roll() {
static float fadeOut(float progress, float min, float max)
=> min + (max - min) * (1f - Mathf.Pow(1f - progress, 2f));
static float fadeIn(float progress, float min, float max)
=> min + (max - min) * Mathf.Pow(progress, 2f);
FieldInfo fi = typeof(Player).GetField("_object", BindingFlags.Instance | BindingFlags.NonPublic);
var po = (PlayerObject)fi.GetValue(_gameEngine.player);
var control = (patch_PlayerControl)po.control;
po.leaveField();
var enemyPos = ntMgr.getEnemyPos();
var playerPos = control._playPosition;
var finalRollingFrame = ntMgr.getCurrentFrame();
var rollingStartTime = CustomDateTime.Now;
while(_isRolling) {
TimeSpan timeSpan = CustomDateTime.Now - rollingStartTime;
if(timeSpan <= ROLL_DURATION) {
float frame = (float)(timeSpan.TotalMilliseconds / ROLL_DURATION.TotalMilliseconds);
float num1 = fadeOut(frame, 0f, 1f);
float num2 = fadeIn(frame, 0f, 1f);
ntMgr.setFrameForce(finalRollingFrame * (1f - num1));
ntMgr.EnemyPositionForce = new Vector3(enemyPos.x, enemyPos.y + num2 * 215f, enemyPos.z + num2 * 1600f);
control._playPosition = new Vector3(playerPos.x, playerPos.y, playerPos.z - num2 * 10f);
} else {
_isRolling = false;
ntMgr.EnemyPositionForce = null;
finishRestart();
yield break;
}
yield return new WaitForEndOfFrame();
}
}
private void skipPlay() {
Singleton<Mod.State>.instance.SkipPlay = true;
setNextState(EState.End);
destroy();
ntMgr.stopPlay();
_gameEngine.destroyAllies();
_gameEngine.finishGame();
_gameEngine.playFinish();
}
}