上传文件至 Cheat
This commit is contained in:
102
Cheat/AllCollection.cs
Normal file
102
Cheat/AllCollection.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using HarmonyLib;
|
||||
using MAI2.Util;
|
||||
using Manager;
|
||||
using Manager.MaiStudio;
|
||||
using Manager.UserDatas;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class AllCollection
|
||||
{
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(UserData), "get_FrameList")]
|
||||
public static void FrameList(ref List<UserItem> __result, CollectionProcess __instance)
|
||||
{
|
||||
List<int> list2 = (from i in __result
|
||||
where i.stock > 0
|
||||
select i.itemId).ToList();
|
||||
|
||||
foreach (KeyValuePair<int, FrameData> frame2 in Singleton<DataManager>.Instance.GetFrames())
|
||||
{
|
||||
if (!list2.Contains(frame2.Value.GetID()))
|
||||
{
|
||||
list2.Add(frame2.Value.GetID());
|
||||
__result.Add(new UserItem(frame2.Value.GetID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(UserData), "get_IconList")]
|
||||
public static void IconList(ref List<UserItem> __result, CollectionProcess __instance)
|
||||
{
|
||||
List<int> list2 = (from i in __result
|
||||
where i.stock > 0
|
||||
select i.itemId).ToList();
|
||||
|
||||
foreach (KeyValuePair<int, IconData> icon2 in Singleton<DataManager>.Instance.GetIcons())
|
||||
{
|
||||
if (!list2.Contains(icon2.Value.GetID()))
|
||||
{
|
||||
list2.Add(icon2.Value.GetID());
|
||||
__result.Add(new UserItem(icon2.Value.GetID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(UserData), "get_PlateList")]
|
||||
public static void PlateList(ref List<UserItem> __result, CollectionProcess __instance)
|
||||
{
|
||||
List<int> list2 = (from i in __result
|
||||
where i.stock > 0
|
||||
select i.itemId).ToList();
|
||||
|
||||
foreach (KeyValuePair<int, PlateData> plate2 in Singleton<DataManager>.Instance.GetPlates())
|
||||
{
|
||||
if (!list2.Contains(plate2.Value.GetID()))
|
||||
{
|
||||
list2.Add(plate2.Value.GetID());
|
||||
__result.Add(new UserItem(plate2.Value.GetID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(UserData), "get_PartnerList")]
|
||||
public static void PartnerList(ref List<UserItem> __result, CollectionProcess __instance)
|
||||
{
|
||||
List<int> list2 = (from i in __result
|
||||
where i.stock > 0
|
||||
select i.itemId).ToList();
|
||||
|
||||
foreach (KeyValuePair<int, PartnerData> partner2 in Singleton<DataManager>.Instance.GetPartners())
|
||||
{
|
||||
if (!list2.Contains(partner2.Value.GetID()))
|
||||
{
|
||||
list2.Add(partner2.Value.GetID());
|
||||
__result.Add(new UserItem(partner2.Value.GetID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(UserData), "get_TitleList")]
|
||||
public static void TitleList(ref List<UserItem> __result, CollectionProcess __instance)
|
||||
{
|
||||
List<int> list2 = (from i in __result
|
||||
where i.stock > 0
|
||||
select i.itemId).ToList();
|
||||
|
||||
foreach (KeyValuePair<int, TitleData> title2 in Singleton<DataManager>.Instance.GetTitles())
|
||||
{
|
||||
if (!list2.Contains(title2.Value.GetID()))
|
||||
{
|
||||
list2.Add(title2.Value.GetID());
|
||||
__result.Add(new UserItem(title2.Value.GetID()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
283
Cheat/AutoPlay.cs
Normal file
283
Cheat/AutoPlay.cs
Normal file
@@ -0,0 +1,283 @@
|
||||
using HarmonyLib;
|
||||
using MAI2.Util;
|
||||
using Manager;
|
||||
using Monitor;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using static NoteJudge;
|
||||
using MelonLoader;
|
||||
|
||||
namespace SinmaiAssist.Cheat
|
||||
{
|
||||
public class AutoPlay
|
||||
{
|
||||
public enum AutoPlayMode
|
||||
{
|
||||
None,
|
||||
Critical,
|
||||
Perfect,
|
||||
Great,
|
||||
Good,
|
||||
Random,
|
||||
RandomAllPerfect,
|
||||
RandomFullComboPlus,
|
||||
RandomFullCombo
|
||||
}
|
||||
|
||||
private static readonly ReadOnlyCollection<NoteJudge.ETiming> RandCriticalTiming = Array.AsReadOnly(new NoteJudge.ETiming[5]
|
||||
{
|
||||
NoteJudge.ETiming.FastPerfect2nd,
|
||||
NoteJudge.ETiming.FastPerfect,
|
||||
NoteJudge.ETiming.Critical,
|
||||
NoteJudge.ETiming.LatePerfect,
|
||||
NoteJudge.ETiming.LatePerfect2nd
|
||||
});
|
||||
|
||||
private static readonly ReadOnlyCollection<NoteJudge.ETiming> RandomJudgeTiming = Array.AsReadOnly(new NoteJudge.ETiming[]
|
||||
{
|
||||
NoteJudge.ETiming.Critical,
|
||||
NoteJudge.ETiming.FastPerfect,
|
||||
NoteJudge.ETiming.FastPerfect2nd,
|
||||
NoteJudge.ETiming.LatePerfect,
|
||||
NoteJudge.ETiming.LatePerfect2nd,
|
||||
NoteJudge.ETiming.LateGreat2nd,
|
||||
NoteJudge.ETiming.FastGreat2nd,
|
||||
NoteJudge.ETiming.LateGood,
|
||||
NoteJudge.ETiming.FastGood,
|
||||
NoteJudge.ETiming.TooLate
|
||||
});
|
||||
|
||||
public static AutoPlayMode autoPlayMode = AutoPlayMode.None;
|
||||
public static bool DisableUpdate = false;
|
||||
|
||||
public static bool IsAutoPlay()
|
||||
{
|
||||
return autoPlayMode != AutoPlayMode.None;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(GameManager), "IsAutoPlay")]
|
||||
public static bool SetIsAutoPlay(ref bool __result)
|
||||
{
|
||||
__result = IsAutoPlay();
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(GameManager), "set_AutoPlay")]
|
||||
public static void AutoPlayUpdate()
|
||||
{
|
||||
var mode = GameManager.AutoPlay;
|
||||
if (DisableUpdate) return;
|
||||
autoPlayMode = (AutoPlayMode)mode;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(GameManager), "AutoJudge")]
|
||||
public static void AutoJudge(ref NoteJudge.ETiming __result)
|
||||
{
|
||||
var random = UnityEngine.Random.Range(0, 1000);
|
||||
var random2 = 2;
|
||||
if (random < 350)
|
||||
{
|
||||
random2 += UnityEngine.Random.Range(-2, 3);
|
||||
}
|
||||
|
||||
switch (autoPlayMode)
|
||||
{
|
||||
case AutoPlayMode.Critical:
|
||||
__result = NoteJudge.ETiming.Critical;
|
||||
break;
|
||||
case AutoPlayMode.Perfect:
|
||||
__result = UnityEngine.Random.Range(0, 2) == 0
|
||||
? NoteJudge.ETiming.LatePerfect2nd
|
||||
: NoteJudge.ETiming.FastPerfect2nd;
|
||||
break;
|
||||
case AutoPlayMode.Great:
|
||||
__result = UnityEngine.Random.Range(0, 2) == 0
|
||||
? NoteJudge.ETiming.LateGreat
|
||||
: NoteJudge.ETiming.FastGreat;
|
||||
break;
|
||||
case AutoPlayMode.Good:
|
||||
__result = UnityEngine.Random.Range(0, 2) == 0
|
||||
? NoteJudge.ETiming.LateGood
|
||||
: NoteJudge.ETiming.FastGood;
|
||||
break;
|
||||
case AutoPlayMode.Random:
|
||||
__result = RandomJudgeTiming[UnityEngine.Random.Range(0, RandomJudgeTiming.Count)];
|
||||
break;
|
||||
case AutoPlayMode.RandomAllPerfect:
|
||||
__result = RandCriticalTiming[random2];
|
||||
break;
|
||||
case AutoPlayMode.RandomFullComboPlus:
|
||||
if (random >= 10)
|
||||
{
|
||||
__result = RandCriticalTiming[random2];
|
||||
}
|
||||
else
|
||||
{
|
||||
__result = UnityEngine.Random.Range(0, 2) == 1
|
||||
? NoteJudge.ETiming.LateGreat
|
||||
: NoteJudge.ETiming.FastGreat;
|
||||
}
|
||||
break;
|
||||
case AutoPlayMode.RandomFullCombo:
|
||||
if (random >= 80)
|
||||
{
|
||||
__result = RandCriticalTiming[random2];
|
||||
}
|
||||
else if (random >= 20)
|
||||
{
|
||||
__result = UnityEngine.Random.Range(0, 2) == 1
|
||||
? NoteJudge.ETiming.LateGreat
|
||||
: NoteJudge.ETiming.FastGreat;
|
||||
}
|
||||
else
|
||||
{
|
||||
__result = UnityEngine.Random.Range(0, 2) == 1
|
||||
? NoteJudge.ETiming.LateGood
|
||||
: NoteJudge.ETiming.FastGood;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
__result = NoteJudge.ETiming.TooFast;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(NoteBase), "SetAutoPlayJudge")]
|
||||
public static bool NoteBaseAutoPlayJudge(NoteBase __instance)
|
||||
{
|
||||
if (!IsAutoPlay()) return true;
|
||||
var appearMsec = (float)AccessTools.Field(typeof(NoteBase), "AppearMsec").GetValue(__instance);
|
||||
var isExNote = (bool)AccessTools.Field(typeof(NoteBase), "IsExNote").GetValue(__instance);
|
||||
var playJudgeSeMethod = AccessTools.Method(typeof(NoteBase), "PlayJudgeSe");
|
||||
|
||||
if (NotesManager.GetCurrentMsec() > appearMsec - 4.1666665f && IsAutoPlay())
|
||||
{
|
||||
if ((autoPlayMode == AutoPlayMode.RandomAllPerfect || autoPlayMode == AutoPlayMode.RandomFullCombo || autoPlayMode == AutoPlayMode.RandomFullComboPlus) && isExNote)
|
||||
{
|
||||
AccessTools.Field(typeof(NoteBase), "JudgeResult").SetValue(__instance, NoteJudge.ETiming.Critical);
|
||||
}
|
||||
else
|
||||
{
|
||||
AccessTools.Field(typeof(Monitor.NoteBase), "JudgeResult").SetValue(__instance, GameManager.AutoJudge());
|
||||
}
|
||||
playJudgeSeMethod.Invoke(__instance, null);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(SlideRoot), "Judge")]
|
||||
public static bool SlideRootJudge(SlideRoot __instance, ref bool __result)
|
||||
{
|
||||
if (!IsAutoPlay()) return true;
|
||||
|
||||
// 检查是否进入判定窗口
|
||||
var isNoteCheckTimeStartMethod = AccessTools.Method(typeof(SlideRoot), "IsNoteCheckTimeStart");
|
||||
bool isNoteCheckTimeStart = (bool)isNoteCheckTimeStartMethod.Invoke(
|
||||
__instance,
|
||||
new object[] { Singleton<GamePlayManager>.Instance.GetGameScore(__instance.MonitorId).UserOption.GetJudgeTimingFrame() }
|
||||
);
|
||||
|
||||
if (!isNoteCheckTimeStart)
|
||||
{
|
||||
__result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// ★ 强制所有 Slide 判定为 Critical
|
||||
var judgeResultField = AccessTools.Field(typeof(SlideRoot), "JudgeResult");
|
||||
judgeResultField.SetValue(__instance, NoteJudge.ETiming.Critical);
|
||||
|
||||
__result = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(TouchNoteB), "Judge")]
|
||||
public static bool TouchNoteBJudge(TouchNoteB __instance, ref bool __result)
|
||||
{
|
||||
if (!IsAutoPlay()) return true;
|
||||
var isNoteCheckTimeStartMethod = AccessTools.Method(typeof(NoteBase), "IsNoteCheckTimeStart");
|
||||
bool isNoteCheckTimeStart = (bool)isNoteCheckTimeStartMethod.Invoke(__instance, new object[] { Singleton<GamePlayManager>.Instance.GetGameScore(__instance.MonitorId).UserOption.GetJudgeTimingFrame() });
|
||||
if (isNoteCheckTimeStart)
|
||||
{
|
||||
__result = false;
|
||||
return false;
|
||||
}
|
||||
var judgeTimingDiffMsecField = AccessTools.Field(typeof(NoteBase), "JudgeTimingDiffMsec");
|
||||
var judgeResultField = AccessTools.Field(typeof(NoteBase), "JudgeResult");
|
||||
var appearMsecField = AccessTools.Field(typeof(NoteBase), "AppearMsec");
|
||||
var judgeTypeField = AccessTools.Field(typeof(NoteBase), "JudgeType");
|
||||
var buttonIdField = AccessTools.Field(typeof(NoteBase), "ButtonId");
|
||||
var TouchAreaField = AccessTools.Field(typeof(TouchNoteB), "TouchArea");
|
||||
var playJudgeSeMethod = AccessTools.Method(typeof(TouchNoteB), "PlayJudgeSe");
|
||||
|
||||
var judgeTimingDiffMsec = NotesManager.GetCurrentMsec() - (float)appearMsecField.GetValue(__instance);
|
||||
judgeTimingDiffMsecField.SetValue(__instance, judgeTimingDiffMsec);
|
||||
|
||||
ETiming judgeResult = (ETiming)judgeResultField.GetValue(__instance);
|
||||
judgeResult = NoteJudge.GetJudgeTiming(ref judgeTimingDiffMsec, Singleton<GamePlayManager>.Instance.GetGameScore(__instance.MonitorId).UserOption.GetJudgeTimingFrame(), (EJudgeType)judgeTypeField.GetValue(__instance));
|
||||
if (autoPlayMode == AutoPlayMode.RandomAllPerfect ||
|
||||
autoPlayMode == AutoPlayMode.RandomFullComboPlus ||
|
||||
autoPlayMode == AutoPlayMode.RandomFullCombo)
|
||||
{
|
||||
judgeResult = NoteJudge.ETiming.Critical;
|
||||
}
|
||||
judgeResultField.SetValue(__instance, judgeResult);
|
||||
|
||||
TouchSensorType touchArea = (TouchSensorType)TouchAreaField.GetValue(__instance);
|
||||
if (judgeResult != NoteJudge.ETiming.End)
|
||||
{
|
||||
playJudgeSeMethod.Invoke(__instance, null);
|
||||
int buttonId = (int)buttonIdField.GetValue(__instance);
|
||||
if (touchArea == TouchSensorType.B)
|
||||
{
|
||||
InputManager.SetUsedThisFrame(__instance.MonitorId, (InputManager.TouchPanelArea)(8 + buttonId));
|
||||
}
|
||||
else if (touchArea == TouchSensorType.E)
|
||||
{
|
||||
InputManager.SetUsedThisFrame(__instance.MonitorId, (InputManager.TouchPanelArea)(26 + buttonId));
|
||||
}
|
||||
else if (touchArea == TouchSensorType.A)
|
||||
{
|
||||
InputManager.SetUsedThisFrame(__instance.MonitorId, (InputManager.TouchPanelArea)(0 + buttonId));
|
||||
}
|
||||
else if (touchArea == TouchSensorType.D)
|
||||
{
|
||||
InputManager.SetUsedThisFrame(__instance.MonitorId, (InputManager.TouchPanelArea)(18 + buttonId));
|
||||
}
|
||||
else if (touchArea == TouchSensorType.C)
|
||||
{
|
||||
InputManager.SetUsedThisFrame(__instance.MonitorId, InputManager.TouchPanelArea.C1);
|
||||
InputManager.SetUsedThisFrame(__instance.MonitorId, InputManager.TouchPanelArea.C2);
|
||||
}
|
||||
__result = true;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(TouchNoteB), "NoteCheck")]
|
||||
public static void NoteCheck(TouchNoteB __instance)
|
||||
{
|
||||
if (!IsAutoPlay()) return;
|
||||
var judgeResultField = AccessTools.Field(typeof(NoteBase), "JudgeResult");
|
||||
var playJudgeSeMethod = AccessTools.Method(typeof(TouchNoteB), "PlayJudgeSe");
|
||||
float appearMsec = (float)AccessTools.Field(typeof(NoteBase), "AppearMsec").GetValue(__instance);
|
||||
if ((autoPlayMode == AutoPlayMode.RandomAllPerfect ||
|
||||
autoPlayMode == AutoPlayMode.RandomFullComboPlus ||
|
||||
autoPlayMode == AutoPlayMode.RandomFullCombo) &&
|
||||
NotesManager.GetCurrentMsec() > appearMsec - 4.1666665f &&
|
||||
IsAutoPlay())
|
||||
{
|
||||
judgeResultField.SetValue(__instance, NoteJudge.ETiming.Critical);
|
||||
playJudgeSeMethod.Invoke(__instance, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
285
Cheat/ChartController.cs
Normal file
285
Cheat/ChartController.cs
Normal file
@@ -0,0 +1,285 @@
|
||||
using DB;
|
||||
using HarmonyLib;
|
||||
using MAI2.Util;
|
||||
using Manager;
|
||||
using MelonLoader;
|
||||
using Monitor;
|
||||
using Process;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class ChartController
|
||||
{
|
||||
private enum GameSequence
|
||||
{
|
||||
Init,
|
||||
Sync,
|
||||
Start,
|
||||
StartWait,
|
||||
Play,
|
||||
PlayEnd,
|
||||
Result,
|
||||
ResultEnd,
|
||||
FinalWait,
|
||||
Release
|
||||
}
|
||||
|
||||
public enum Button
|
||||
{
|
||||
None,
|
||||
Pause,
|
||||
Reset,
|
||||
TimeSkipAdd,
|
||||
TimeSkipAdd2,
|
||||
TimeSkipAdd3,
|
||||
TimeSkipSub,
|
||||
TimeSkipSub2,
|
||||
TimeSkipSub3,
|
||||
Set,
|
||||
Back
|
||||
}
|
||||
|
||||
public static Button ButtonStatus = Button.None;
|
||||
public static bool IsPlaying = false;
|
||||
public static double Timer = 0.0;
|
||||
public static int RecordTime = 0;
|
||||
private static MovieController _gameMovie;
|
||||
private static NotesManager _notesManager;
|
||||
private static GameProcess _gameProcess;
|
||||
private static GameMonitor[] _monitors;
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(GameProcess), "OnUpdate")]
|
||||
private static void OnUpdate(GameProcess __instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
_gameProcess = __instance;
|
||||
GameSequence sequence = (GameSequence)typeof(GameProcess).GetField("_sequence", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
|
||||
_monitors = (GameMonitor[])typeof(GameProcess).GetField("_monitors", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(_gameProcess);
|
||||
_gameMovie = (MovieController)typeof(GameProcess).GetField("_gameMovie", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
|
||||
_notesManager = new NotesManager();
|
||||
if (!_notesManager.IsPlaying())
|
||||
{
|
||||
IsPlaying = true;
|
||||
Timer = 0.0;
|
||||
RecordTime = 0;
|
||||
}
|
||||
if (sequence == GameSequence.Play)
|
||||
{
|
||||
var IsPartyPlayMethod = typeof(GameProcess).GetMethod("IsPartyPlay", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
bool IsPartyPlay = (bool)IsPartyPlayMethod.Invoke(__instance, null);
|
||||
if (IsPlaying)
|
||||
{
|
||||
Timer += GameManager.GetGameMSecAddD();
|
||||
}
|
||||
if (ButtonStatus == Button.Pause || DebugInput.GetKeyDown(SinmaiAssist.KeyBindConfig.ChartController.Pause.KeyCode))
|
||||
{
|
||||
if (IsPlaying)
|
||||
{
|
||||
SoundManager.PauseMusic(true);
|
||||
GameMoviePause(true);
|
||||
NotesManager.Pause(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
SoundManager.PauseMusic(false);
|
||||
GameMoviePause(false);
|
||||
NotesManager.Pause(false);
|
||||
//TimeSkip(0);
|
||||
}
|
||||
IsPlaying = !IsPlaying;
|
||||
}
|
||||
else if (DebugInput.GetKey(SinmaiAssist.KeyBindConfig.ChartController.Backward.KeyCode) && !IsPlaying)
|
||||
{
|
||||
Singleton<GamePlayManager>.Instance.Initialize(IsPartyPlay);
|
||||
TimeSkip(-16);
|
||||
}
|
||||
else if (DebugInput.GetKey(SinmaiAssist.KeyBindConfig.ChartController.Forward.KeyCode) && !IsPlaying)
|
||||
{
|
||||
Singleton<GamePlayManager>.Instance.Initialize(IsPartyPlay);
|
||||
TimeSkip(16);
|
||||
}
|
||||
else if (DebugInput.GetKeyDown(SinmaiAssist.KeyBindConfig.ChartController.SetRecord.KeyCode) || ButtonStatus == Button.Set)
|
||||
{
|
||||
RecordTime = (int)Timer;
|
||||
MelonLogger.Msg($"Record Time: {RecordTime}");
|
||||
}
|
||||
else if (DebugInput.GetKeyDown(SinmaiAssist.KeyBindConfig.ChartController.ReturnRecord.KeyCode) || ButtonStatus == Button.Back)
|
||||
{
|
||||
int time = RecordTime == 0 ? 999999 : (int)Timer - RecordTime;
|
||||
TimeSkip(-time);
|
||||
TimeSkip(0);
|
||||
MelonLogger.Msg($"Time Jump: {RecordTime}({-time})");
|
||||
}
|
||||
else if (ButtonStatus != Button.None)
|
||||
{
|
||||
Singleton<GamePlayManager>.Instance.Initialize(IsPartyPlay);
|
||||
switch (ButtonStatus)
|
||||
{
|
||||
case Button.TimeSkipAdd:
|
||||
TimeSkip(100);
|
||||
break;
|
||||
case Button.TimeSkipAdd2:
|
||||
TimeSkip(1000);
|
||||
break;
|
||||
case Button.TimeSkipAdd3:
|
||||
TimeSkip(2500);
|
||||
break;
|
||||
case Button.TimeSkipSub:
|
||||
TimeSkip(-100);
|
||||
break;
|
||||
case Button.TimeSkipSub2:
|
||||
TimeSkip(-1000);
|
||||
break;
|
||||
case Button.TimeSkipSub3:
|
||||
TimeSkip(-2500);
|
||||
break;
|
||||
case Button.Reset:
|
||||
Singleton<GamePlayManager>.Instance.SetQuickRetryFrag(flag: true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ReUpdate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void TimeSkip(int addMsec)
|
||||
{
|
||||
GameMoviePause(true);
|
||||
NotesManager.Pause(true);
|
||||
if (addMsec >= 0)
|
||||
{
|
||||
Timer += addMsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
Timer = ((Timer + (double)addMsec >= 0.0) ? (Timer + (double)addMsec) : 0.0);
|
||||
}
|
||||
GameMovieSetSeekFrame(Timer);
|
||||
SoundManager.SeekMusic((int)Timer);
|
||||
for (int i = 0; i < _monitors.Length; i++)
|
||||
{
|
||||
_monitors[i].Seek((int)Timer);
|
||||
}
|
||||
int num = 91;
|
||||
NotesManager.StartPlay((int)Timer + num);
|
||||
NotesManager.Pause(true);
|
||||
if (IsPlaying)
|
||||
{
|
||||
SoundManager.PauseMusic(pause: false);
|
||||
GameMoviePause(false);
|
||||
NotesManager.Pause(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMoviePause(true);
|
||||
}
|
||||
_gameProcess.UpdateNotes();
|
||||
}
|
||||
|
||||
private static void ReUpdate()
|
||||
{
|
||||
int[] _skipPhase = new int[2] { -1, -1 };
|
||||
int[] _retryPhase = new int[2] { -1, -1 };
|
||||
System.Type processBaseType = typeof(GameProcess).BaseType;
|
||||
var containerField = processBaseType.GetField("container", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
ProcessDataContainer container = (ProcessDataContainer)containerField.GetValue(_gameProcess);
|
||||
for (int num30 = 0; num30 < _monitors.Length; num30++)
|
||||
{
|
||||
if (Singleton<GamePlayManager>.Instance.GetGameScore(num30).IsTrackSkip || Singleton<GamePlayManager>.Instance.IsQuickRetry())
|
||||
{
|
||||
for (int num31 = 0; num31 < 35; num31++)
|
||||
{
|
||||
InputManager.SetUsedThisFrame(num30, (InputManager.TouchPanelArea)num31);
|
||||
}
|
||||
}
|
||||
_monitors[num30].ViewUpdate();
|
||||
if (!Singleton<UserDataManager>.Instance.GetUserData(num30).IsEntry)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (_skipPhase[num30] != _monitors[num30].GetPushPhase())
|
||||
{
|
||||
_skipPhase[num30] = _monitors[num30].GetPushPhase();
|
||||
switch (_skipPhase[num30])
|
||||
{
|
||||
case -1:
|
||||
container.processManager.ForcedCloseWindow(num30);
|
||||
break;
|
||||
case 0:
|
||||
container.processManager.EnqueueMessage(num30, WindowMessageID.TrackSkip3Second, WindowPositionID.Middle);
|
||||
break;
|
||||
case 1:
|
||||
container.processManager.EnqueueMessage(num30, WindowMessageID.TrackSkip2Second, WindowPositionID.Middle);
|
||||
break;
|
||||
case 2:
|
||||
container.processManager.EnqueueMessage(num30, WindowMessageID.TrackSkip1Second, WindowPositionID.Middle);
|
||||
break;
|
||||
case 3:
|
||||
container.processManager.CloseWindow(num30);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_retryPhase[num30] != _monitors[num30].GetPushPhaseRetry())
|
||||
{
|
||||
_retryPhase[num30] = _monitors[num30].GetPushPhaseRetry();
|
||||
switch (_retryPhase[num30])
|
||||
{
|
||||
case -1:
|
||||
container.processManager.ForcedCloseWindow(num30);
|
||||
break;
|
||||
case 0:
|
||||
container.processManager.EnqueueMessage(num30, WindowMessageID.QuickRetry2Second, WindowPositionID.Middle);
|
||||
break;
|
||||
case 1:
|
||||
container.processManager.EnqueueMessage(num30, WindowMessageID.QuickRetry1Second, WindowPositionID.Middle);
|
||||
break;
|
||||
case 2:
|
||||
container.processManager.CloseWindow(num30);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Singleton<GamePlayManager>.Instance.PlayLastUpdate();
|
||||
}
|
||||
|
||||
//修复1.55后 因SBGA程序员闲的没事觉得自己不写点东西就要被优化了,灵机一动给GameMovie类下的方法加上屏幕号 导致Mod调用旧方法时让你最新最热原地爆炸的问题
|
||||
private static void GameMoviePause(bool pause)
|
||||
{
|
||||
var method = _gameMovie.GetType().GetMethod("Pause");
|
||||
if (method.GetParameters().Length == 1)
|
||||
{
|
||||
method.Invoke(_gameMovie, [pause]);
|
||||
}
|
||||
else
|
||||
{
|
||||
method.Invoke(_gameMovie, [0, pause]);
|
||||
method.Invoke(_gameMovie, [1, pause]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void GameMovieSetSeekFrame(double msec)
|
||||
{
|
||||
var method = _gameMovie.GetType().GetMethod("SetSeekFrame");
|
||||
if (method.GetParameters().Length == 1)
|
||||
{
|
||||
method.Invoke(_gameMovie, [msec]);
|
||||
}
|
||||
else
|
||||
{
|
||||
method.Invoke(_gameMovie, [0, msec]);
|
||||
method.Invoke(_gameMovie, [1, msec]);
|
||||
}
|
||||
}
|
||||
}
|
||||
290
Cheat/FastSkip.cs
Normal file
290
Cheat/FastSkip.cs
Normal file
@@ -0,0 +1,290 @@
|
||||
using HarmonyLib;
|
||||
using MAI2.Util;
|
||||
using Manager;
|
||||
using Manager.UserDatas;
|
||||
using MelonLoader;
|
||||
using Monitor;
|
||||
using Process;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
internal class FastSkip
|
||||
{
|
||||
private enum GameSequence
|
||||
{
|
||||
Init,
|
||||
Sync,
|
||||
Start,
|
||||
StartWait,
|
||||
Play,
|
||||
PlayEnd,
|
||||
Result,
|
||||
ResultEnd,
|
||||
FinalWait,
|
||||
Release
|
||||
}
|
||||
|
||||
public static bool CustomSkip = false;
|
||||
public static bool SkipButton = false;
|
||||
public static bool Force1Miss = false;
|
||||
public static int CustomAchivement = 0;
|
||||
|
||||
private static bool _isSkip = false;
|
||||
private static bool _Miss = false;
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(GameProcess), "OnUpdate")]
|
||||
public static void Skip(GameProcess __instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Type processBaseType = typeof(GameProcess).BaseType;
|
||||
GameSequence _sequence = (GameSequence)typeof(GameProcess).GetField("_sequence", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
|
||||
var UpdateSubbMonitorDataMethod = typeof(GameProcess).GetMethod("UpdateSubbMonitorData", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var SetReleaseMethod = typeof(GameProcess).GetMethod("SetRelease", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var IsPartyPlayMethod = typeof(GameProcess).GetMethod("IsPartyPlay", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var containerField = processBaseType.GetField("container", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
ProcessDataContainer container = (ProcessDataContainer)containerField.GetValue(__instance);
|
||||
if (_sequence >= GameSequence.Play && _sequence < GameSequence.Release && !GameManager.IsNoteCheckMode)
|
||||
{
|
||||
_isSkip = false;
|
||||
if (DebugInput.GetKeyDown(KeyCode.Space) || SkipButton)
|
||||
{
|
||||
_isSkip = true;
|
||||
GameMonitor[] monitors = (GameMonitor[])typeof(GameProcess).GetField("_monitors", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
|
||||
if (CustomSkip)
|
||||
{
|
||||
for (int i = 0; i < monitors.Length; i++)
|
||||
{
|
||||
monitors[i].Seek(0);
|
||||
}
|
||||
NotesManager.StartPlay(0);
|
||||
NotesManager.Pause(true);
|
||||
bool IsPartyPlay = (bool)IsPartyPlayMethod.Invoke(__instance, null);
|
||||
Singleton<GamePlayManager>.Instance.Initialize(IsPartyPlay);
|
||||
uint maxCombo = 0u;
|
||||
for (int i = 0; i < monitors.Length; i++)
|
||||
{
|
||||
if (Singleton<UserDataManager>.Instance.GetUserData(i).IsEntry)
|
||||
{
|
||||
monitors[i].ForceAchivement(CustomAchivement, 0);
|
||||
maxCombo += Singleton<GamePlayManager>.Instance.GetGameScore(i).MaxCombo;
|
||||
}
|
||||
}
|
||||
GameScoreList gameScore = Singleton<GamePlayManager>.Instance.GetGameScore(2);
|
||||
if (gameScore.IsEnable && !gameScore.IsHuman())
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (Singleton<UserDataManager>.Instance.GetUserData(i).IsEntry && GameManager.SelectGhostID[i] != GhostManager.GhostTarget.End)
|
||||
{
|
||||
UserGhost ghostToEnum = Singleton<GhostManager>.Instance.GetGhostToEnum(GameManager.SelectGhostID[i]);
|
||||
gameScore.SetForceAchivement_Battle((float)GameManager.ConvAchiveIntToDecimal(ghostToEnum.Achievement));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < monitors.Length; i++)
|
||||
{
|
||||
if (Singleton<UserDataManager>.Instance.GetUserData(i).IsEntry)
|
||||
{
|
||||
Singleton<GamePlayManager>.Instance.GetGameScore(i).SetChain(maxCombo);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_isSkip)
|
||||
{
|
||||
for (int i = 0; i < monitors.Length; i++)
|
||||
{
|
||||
if (Singleton<UserDataManager>.Instance.GetUserData(i).IsEntry)
|
||||
{
|
||||
UpdateSubbMonitorDataMethod.Invoke(__instance, new object[] { i });
|
||||
Message[] message = (Message[])typeof(GameProcess).GetField("_message", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
|
||||
container.processManager.SendMessage(message[i]);
|
||||
Singleton<GamePlayManager>.Instance.SetSyncResult(i);
|
||||
}
|
||||
}
|
||||
SetReleaseMethod.Invoke(__instance, null);
|
||||
SkipButton = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
MelonLogger.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(GameScoreList), "SetForceAchivement")]
|
||||
public static bool SetForceAchivement(int achivement, int dxscore, GameScoreList __instance)
|
||||
{
|
||||
decimal num1 = achivement;
|
||||
if (num1 >= 100.0m && num1 <= 100.4m) num1 = 100.3m;
|
||||
long num2;
|
||||
long num3;
|
||||
if (num1 > 100.0m)
|
||||
{
|
||||
num2 = (long)((decimal)__instance.ScoreTotal._allPerfectScore * (num1 - 1.0m) * 0.01m);
|
||||
num3 = __instance.ScoreTotal._breakBonusScore;
|
||||
}
|
||||
else
|
||||
{
|
||||
num2 = (long)((decimal)__instance.ScoreTotal._allPerfectScore * (num1 * 0.99m * 0.01m));
|
||||
num3 = (long)((decimal)__instance.ScoreTotal._breakBonusScore * num1 * 0.01m);
|
||||
}
|
||||
NoteJudge.ETiming[] NoteArray = new NoteJudge.ETiming[7]
|
||||
{
|
||||
NoteJudge.ETiming.Critical,
|
||||
NoteJudge.ETiming.FastGreat,
|
||||
NoteJudge.ETiming.FastGreat2nd,
|
||||
NoteJudge.ETiming.LateGreat,
|
||||
NoteJudge.ETiming.LateGreat2nd,
|
||||
NoteJudge.ETiming.LateGreat3rd,
|
||||
NoteJudge.ETiming.LateGood
|
||||
};
|
||||
int monitorIndex = (int)typeof(GameScoreList).GetField("_monitorIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(__instance);
|
||||
NoteDataList noteList = NotesManager.Instance(monitorIndex).getReader().GetNoteList();
|
||||
foreach (NoteData item in noteList)
|
||||
{
|
||||
if (!item.type.isBreakScore())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
bool flag = false;
|
||||
NoteJudge.ETiming[] array2 = NoteArray;
|
||||
foreach (NoteJudge.ETiming eTiming in array2)
|
||||
{
|
||||
NoteScore.EScoreType eScoreType = GamePlayManager.NoteType2ScoreType(item.type.getEnum());
|
||||
if (0m <= (decimal)(num2 - NoteScore.GetJudgeScore(eTiming, NoteScore.EScoreType.Break)) && 0m <= (decimal)(num3 - NoteScore.GetJudgeScore(eTiming, NoteScore.EScoreType.BreakBonus)))
|
||||
{
|
||||
num2 -= NoteScore.GetJudgeScore(eTiming, eScoreType);
|
||||
num3 -= NoteScore.GetJudgeScore(eTiming, NoteScore.EScoreType.BreakBonus);
|
||||
__instance.SetResult(item.indexNote, eScoreType, eTiming);
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag)
|
||||
{
|
||||
__instance.SetResult(item.indexNote, NoteScore.EScoreType.Break, NoteJudge.ETiming.TooFast);
|
||||
_Miss = true;
|
||||
}
|
||||
}
|
||||
int num4 = 0;
|
||||
int num5 = 0;
|
||||
long num6 = 0L;
|
||||
for (int j = 0; j < NoteArray.Length; j++)
|
||||
{
|
||||
long num7 = num2;
|
||||
long num8 = 0L;
|
||||
num8 += __instance.ScoreTotal.GetTapNum() * NoteScore.GetJudgeScore(NoteArray[j]);
|
||||
num8 += __instance.ScoreTotal.GetHoldNum() * NoteScore.GetJudgeScore(NoteArray[j], NoteScore.EScoreType.Hold);
|
||||
num8 += __instance.ScoreTotal.GetSlideNum() * NoteScore.GetJudgeScore(NoteArray[j], NoteScore.EScoreType.Slide);
|
||||
num8 += __instance.ScoreTotal.GetTouchNum() * NoteScore.GetJudgeScore(NoteArray[j], NoteScore.EScoreType.Touch);
|
||||
if (num8 <= num7)
|
||||
{
|
||||
num6 = num7 - num8;
|
||||
num5 = ((num4 != 0) ? (num4 - 1) : 0);
|
||||
break;
|
||||
}
|
||||
num4++;
|
||||
}
|
||||
if (num4 >= NoteArray.Length)
|
||||
{
|
||||
num4 = NoteArray.Length - 1;
|
||||
}
|
||||
foreach (NoteData item2 in noteList)
|
||||
{
|
||||
if (item2.type.isSlideScore())
|
||||
{
|
||||
NoteScore.EScoreType eScoreType2 = GamePlayManager.NoteType2ScoreType(item2.type.getEnum());
|
||||
NoteJudge.ETiming eTiming2 = NoteArray[num4];
|
||||
NoteJudge.ETiming eTiming3 = NoteArray[num5];
|
||||
if (0m <= (decimal)num6 && 0m <= (decimal)(num2 - NoteScore.GetJudgeScore(eTiming3, eScoreType2)))
|
||||
{
|
||||
num6 -= NoteScore.GetJudgeScore(eTiming3, eScoreType2) - NoteScore.GetJudgeScore(eTiming2, eScoreType2);
|
||||
num2 -= NoteScore.GetJudgeScore(eTiming3, eScoreType2);
|
||||
__instance.SetResult(item2.indexNote, eScoreType2, eTiming3);
|
||||
}
|
||||
else if (0m <= (decimal)(num2 - NoteScore.GetJudgeScore(eTiming2, eScoreType2)))
|
||||
{
|
||||
num2 -= NoteScore.GetJudgeScore(eTiming2, eScoreType2);
|
||||
__instance.SetResult(item2.indexNote, eScoreType2, eTiming2);
|
||||
}
|
||||
else
|
||||
{
|
||||
__instance.SetResult(item2.indexNote, eScoreType2, NoteJudge.ETiming.TooFast);
|
||||
_Miss = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (NoteData item3 in noteList)
|
||||
{
|
||||
if (item3.type.isHoldScore())
|
||||
{
|
||||
NoteScore.EScoreType eScoreType3 = GamePlayManager.NoteType2ScoreType(item3.type.getEnum());
|
||||
NoteJudge.ETiming eTiming4 = NoteArray[num4];
|
||||
NoteJudge.ETiming eTiming5 = NoteArray[num5];
|
||||
if (0m <= (decimal)num6 && 0m <= (decimal)(num2 - NoteScore.GetJudgeScore(eTiming5, eScoreType3)))
|
||||
{
|
||||
num6 -= NoteScore.GetJudgeScore(eTiming5, eScoreType3) - NoteScore.GetJudgeScore(eTiming4, eScoreType3);
|
||||
num2 -= NoteScore.GetJudgeScore(eTiming5, eScoreType3);
|
||||
__instance.SetResult(item3.indexNote, eScoreType3, eTiming5);
|
||||
}
|
||||
else if (0m <= (decimal)(num2 - NoteScore.GetJudgeScore(eTiming4, eScoreType3)))
|
||||
{
|
||||
num2 -= NoteScore.GetJudgeScore(eTiming4, eScoreType3);
|
||||
__instance.SetResult(item3.indexNote, eScoreType3, eTiming4);
|
||||
}
|
||||
else
|
||||
{
|
||||
__instance.SetResult(item3.indexNote, eScoreType3, NoteJudge.ETiming.TooFast);
|
||||
_Miss = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (NoteData item4 in noteList)
|
||||
{
|
||||
if (item4.type.isTapScore())
|
||||
{
|
||||
NoteScore.EScoreType eScoreType4 = GamePlayManager.NoteType2ScoreType(item4.type.getEnum());
|
||||
NoteJudge.ETiming eTiming6 = NoteArray[num4];
|
||||
NoteJudge.ETiming eTiming7 = NoteArray[num5];
|
||||
if (Force1Miss && !_Miss)
|
||||
{
|
||||
__instance.SetResult(item4.indexNote, eScoreType4, NoteJudge.ETiming.TooFast);
|
||||
_Miss = true;
|
||||
continue;
|
||||
}
|
||||
if (0m < (decimal)num6 && 0m <= (decimal)(num2 - NoteScore.GetJudgeScore(eTiming7, eScoreType4)))
|
||||
{
|
||||
num6 -= NoteScore.GetJudgeScore(eTiming7, eScoreType4) - NoteScore.GetJudgeScore(eTiming6, eScoreType4);
|
||||
num2 -= NoteScore.GetJudgeScore(eTiming7, eScoreType4);
|
||||
__instance.SetResult(item4.indexNote, eScoreType4, eTiming7);
|
||||
}
|
||||
else if (0m <= (decimal)(num2 - NoteScore.GetJudgeScore(eTiming6, eScoreType4)))
|
||||
{
|
||||
num2 -= NoteScore.GetJudgeScore(eTiming6, eScoreType4);
|
||||
__instance.SetResult(item4.indexNote, eScoreType4, eTiming6);
|
||||
}
|
||||
else if (0m < (decimal)num2)
|
||||
{
|
||||
num2 -= NoteScore.GetJudgeScore(eTiming6, eScoreType4);
|
||||
__instance.SetResult(item4.indexNote, eScoreType4, eTiming6);
|
||||
}
|
||||
else
|
||||
{
|
||||
__instance.SetResult(item4.indexNote, eScoreType4, NoteJudge.ETiming.TooFast);
|
||||
_Miss = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
99
Cheat/ForceCurrentIsBest.cs
Normal file
99
Cheat/ForceCurrentIsBest.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using HarmonyLib;
|
||||
using Manager;
|
||||
using Manager.UserDatas;
|
||||
using MelonLoader;
|
||||
using Process;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection.Emit;
|
||||
using DB;
|
||||
using Game;
|
||||
using Datas;
|
||||
using MAI2.Util;
|
||||
using Manager.MaiStudio;
|
||||
using Monitor;
|
||||
|
||||
namespace SinmaiAssist.Cheat
|
||||
{
|
||||
public class ForceCurrentIsBest
|
||||
{
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(ResultProcess), "OnStart")]
|
||||
|
||||
public static void Postfix(ResultProcess __instance)
|
||||
{
|
||||
try
|
||||
{
|
||||
var userDataField = AccessTools.Field(typeof(ResultProcess), "_userData");
|
||||
var userScoresField = AccessTools.Field(typeof(ResultProcess), "_userScores");
|
||||
var musicIDField = AccessTools.Field(typeof(ResultProcess), "_musicID");
|
||||
var isNewRecordField = AccessTools.Field(typeof(ResultProcess), "_isNewRecord");
|
||||
var monitorsField = AccessTools.Field(typeof(ResultProcess), "_monitors");
|
||||
var userData = (UserData[])userDataField.GetValue(__instance);
|
||||
var userScores = (UserScore[])userScoresField.GetValue(__instance);
|
||||
int musicID = (int)(musicIDField.GetValue(__instance));
|
||||
var isNewRecord = (bool[])(isNewRecordField.GetValue(__instance));
|
||||
var monitors = (ResultMonitor[])(monitorsField.GetValue(__instance));
|
||||
|
||||
MusicData music = Singleton<DataManager>.Instance.GetMusic(musicID);
|
||||
if (music == null) return;
|
||||
|
||||
for (int playerIndex = 0; playerIndex < userData.Length; playerIndex++)
|
||||
{
|
||||
if (userData[playerIndex] == null) continue;
|
||||
|
||||
int difficulty = GameManager.SelectDifficultyID[playerIndex];
|
||||
|
||||
if (userData[playerIndex].ScoreDic[difficulty].TryGetValue(musicID, out UserScore historyScore))
|
||||
{
|
||||
bool isDoublePlay = music.utagePlayStyle == UtagePlayStyle.DoublePlayerScore;
|
||||
uint oldAchivement = historyScore.achivement;
|
||||
uint oldDeluxscore = historyScore.deluxscore;
|
||||
|
||||
historyScore.achivement = userScores[playerIndex].achivement;
|
||||
historyScore.combo = userScores[playerIndex].combo;
|
||||
historyScore.sync = userScores[playerIndex].sync;
|
||||
historyScore.deluxscore = userScores[playerIndex].deluxscore;
|
||||
historyScore.scoreRank = GameManager.GetClearRank(
|
||||
(int)historyScore.achivement,
|
||||
isDoublePlay
|
||||
);
|
||||
|
||||
int theoreticalValue = isDoublePlay ? 2020000 : 1010000;
|
||||
if (userScores[playerIndex].achivement >= theoreticalValue)
|
||||
{
|
||||
historyScore.extNum1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
historyScore.extNum1 = 0;//Maybe not necessary
|
||||
}
|
||||
|
||||
isNewRecord[playerIndex] = true;
|
||||
int dxFluctuation = (int)historyScore.deluxscore - (int)oldDeluxscore;
|
||||
int totalNotes = music.notesData[difficulty].maxNotes * 3;
|
||||
int percent = totalNotes > 0 ?
|
||||
(int)(historyScore.deluxscore * 100) / totalNotes : 0;
|
||||
DeluxcorerankrateID dxRank = GameManager.GetDeluxcoreRank(percent);
|
||||
|
||||
monitors[playerIndex].SetDxScore(
|
||||
historyScore.deluxscore,
|
||||
dxFluctuation,
|
||||
totalNotes,
|
||||
dxRank
|
||||
);
|
||||
monitors[playerIndex].SetMyBestAchievement(
|
||||
oldAchivement,
|
||||
historyScore.achivement - oldAchivement,
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MelonLogger.Error($"ForceCurrentIsBestMoudleError: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Cheat/ResetLoginBonusRecord.cs
Normal file
24
Cheat/ResetLoginBonusRecord.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using Net.Packet;
|
||||
using Net.Packet.Mai2;
|
||||
using Net.VO;
|
||||
using Net.VO.Mai2;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class ResetLoginBonusRecord
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(PacketGetUserData), "SafeNullMember")]
|
||||
public static bool SafeNullMember(PacketGetUserData __instance, UserDetailResponseVO src)
|
||||
{
|
||||
if (src.userData.lastLoginDate != null)
|
||||
{
|
||||
src.userData.lastLoginDate = "2000-01-01 00:00:00";
|
||||
src.userData.lastPairLoginDate = "2000-01-01 00:00:00";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
24
Cheat/RewriteLoginBonusStamp.cs
Normal file
24
Cheat/RewriteLoginBonusStamp.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using Net.Packet;
|
||||
using Net.Packet.Mai2;
|
||||
using Net.VO;
|
||||
using Net.VO.Mai2;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class RewriteLoginBonusStamp
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(PacketGetUserLoginBonus), "SafeNullMember")]
|
||||
public static bool SafeNullMember(PacketGetUserData __instance, UserLoginBonusResponseVO src)
|
||||
{
|
||||
if (src.userLoginBonusList == null) return true;
|
||||
for (int i = 0; i < src.userLoginBonusList.Length; i++)
|
||||
{
|
||||
src.userLoginBonusList[i].point = SinmaiAssist.MainConfig.Cheat.RewriteLoginBonusStamp.Point;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
29
Cheat/SetAllCharacterAsSameAndLock.cs
Normal file
29
Cheat/SetAllCharacterAsSameAndLock.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using Net.Packet;
|
||||
using Net.Packet.Mai2;
|
||||
using Net.VO;
|
||||
using Net.VO.Mai2;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class SetAllCharacterAsSameAndLock
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(PacketGetUserData), "SafeNullMember")]
|
||||
public static bool SafeNullMember(PacketGetUserData __instance, UserDetailResponseVO src)
|
||||
{
|
||||
if (src.userData.charaSlot != null)
|
||||
{
|
||||
var newSlot = new[]
|
||||
{
|
||||
src.userData.charaSlot[0], src.userData.charaSlot[0], src.userData.charaSlot[0],
|
||||
src.userData.charaSlot[0], src.userData.charaSlot[0]
|
||||
};
|
||||
src.userData.charaSlot = newSlot;
|
||||
src.userData.charaLockSlot = newSlot;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
64
Cheat/UnlockEvent.cs
Normal file
64
Cheat/UnlockEvent.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using HarmonyLib;
|
||||
using Net.Packet;
|
||||
using Net.Packet.Mai2;
|
||||
using Net.VO;
|
||||
using Net.VO.Mai2;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class UnlockEvent
|
||||
{
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(PacketGetGameEvent), "Proc")]
|
||||
public static void Unlock(PacketGetGameEvent __instance, ref PacketState __result)
|
||||
{
|
||||
if (__result != PacketState.Done) return;
|
||||
NetQuery<GameEventRequestVO, GameEventResponseVO> netQuery = __instance.Query as NetQuery<GameEventRequestVO, GameEventResponseVO>;
|
||||
List<GameEvent> list = new List<GameEvent>();
|
||||
|
||||
ReadAllEvents("./Sinmai_Data/StreamingAssets/", ref list);
|
||||
if (Directory.Exists("./option"))
|
||||
{
|
||||
ReadAllEvents("./option", ref list);
|
||||
}
|
||||
|
||||
netQuery.Response.gameEventList = list.ToArray();
|
||||
FieldInfo onDoneField = typeof(PacketGetGameEvent).GetField("_onDone", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
Action<GameEvent[]> onDone = (Action<GameEvent[]>)onDoneField.GetValue(__instance);
|
||||
onDone?.Invoke(netQuery.Response.gameEventList ?? Array.Empty<GameEvent>());
|
||||
}
|
||||
|
||||
private static void ReadAllEvents(string path, ref List<GameEvent> list)
|
||||
{
|
||||
var rootDir = new DirectoryInfo(path);
|
||||
|
||||
foreach (var optFolder in rootDir.EnumerateDirectories("*", SearchOption.AllDirectories))
|
||||
{
|
||||
var eventPath = Path.Combine(optFolder.FullName, "event");
|
||||
if (int.TryParse(optFolder.Name.Substring(1), out var optNumber) && Directory.Exists(eventPath))
|
||||
{
|
||||
var dir = new DirectoryInfo(eventPath);
|
||||
foreach (var eventFolder in dir.EnumerateDirectories("*", SearchOption.AllDirectories))
|
||||
{
|
||||
if (eventFolder.Name.StartsWith("event") && int.TryParse(eventFolder.Name.Replace("event", ""), out var eventId))
|
||||
{
|
||||
if (eventId > 0)
|
||||
{
|
||||
list.Add(new GameEvent
|
||||
{
|
||||
id = eventId,
|
||||
startDate = "2000-01-01 00:00:00",
|
||||
endDate = "2077-07-21 11:45:14",
|
||||
type = 1
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
Cheat/UnlockMaster.cs
Normal file
32
Cheat/UnlockMaster.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using HarmonyLib;
|
||||
using MAI2.Util;
|
||||
using Manager;
|
||||
using SinmaiAssist.Utils;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class UnlockMaster
|
||||
{
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(NotesListManager), "IsUnlockMaster")]
|
||||
public static void IsUnlockMaster(ref bool __result, ref int id, ref int index)
|
||||
{
|
||||
if (__result == false && SinmaiAssist.MainConfig.Cheat.SaveUnlockMaster)
|
||||
{
|
||||
User.GetUserData(index).AddUnlockMusic(UserData.MusicUnlock.Master, id);
|
||||
}
|
||||
__result = true;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(NotesListManager), "IsUnlockReMaster")]
|
||||
public static void IsUnlockReMaster(ref bool __result, ref int id, ref int index)
|
||||
{
|
||||
if (Singleton<UserDataManager>.Instance.GetUserData(index).IsEntry) return;
|
||||
if (__result == false && SinmaiAssist.MainConfig.Cheat.SaveUnlockMaster)
|
||||
{
|
||||
User.GetUserData(index).AddUnlockMusic(UserData.MusicUnlock.ReMaster, id);
|
||||
}
|
||||
__result = true;
|
||||
}
|
||||
}
|
||||
19
Cheat/UnlockMusic.cs
Normal file
19
Cheat/UnlockMusic.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using HarmonyLib;
|
||||
using Manager;
|
||||
using SinmaiAssist.Utils;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class UnlockMusic
|
||||
{
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(NotesListManager), "IsUnlockBase")]
|
||||
public static void UnlockBase(ref bool __result,ref int id, ref int index)
|
||||
{
|
||||
if (__result == false && SinmaiAssist.MainConfig.Cheat.SaveUnlockMusic)
|
||||
{
|
||||
User.GetUserData(index).AddUnlockMusic(UserData.MusicUnlock.Base, id);
|
||||
}
|
||||
__result = true;
|
||||
}
|
||||
}
|
||||
83
Cheat/UnlockUtage.cs
Normal file
83
Cheat/UnlockUtage.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using MAI2System;
|
||||
using Manager;
|
||||
using Manager.MaiStudio;
|
||||
using MelonLoader;
|
||||
using SinmaiAssist.Utils;
|
||||
|
||||
namespace SinmaiAssist.Cheat;
|
||||
|
||||
public class UnlockUtage
|
||||
{
|
||||
private static List<int> _needDoublePlayerMusicIdList = [];
|
||||
|
||||
private static ForceUtageModeType _forceUtageMode = ForceUtageModeType.Normal;
|
||||
|
||||
private static Dictionary<ForceUtageModeType, string> _utagePathMap = new()
|
||||
{
|
||||
{ ForceUtageModeType.Normal, "" },
|
||||
{ ForceUtageModeType.Force1P, "_L.ma2" },
|
||||
{ ForceUtageModeType.Force2P, "_R.ma2" }
|
||||
};
|
||||
|
||||
private enum ForceUtageModeType
|
||||
{
|
||||
Normal,
|
||||
Force1P,
|
||||
Force2P
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(GameManager), "CanUnlockUtageTotalJudgement")]
|
||||
public static bool ForceUnlockUtage(out ConstParameter.ResultOfUnlockUtageJudgement result1P, out ConstParameter.ResultOfUnlockUtageJudgement result2P)
|
||||
{
|
||||
result1P = ConstParameter.ResultOfUnlockUtageJudgement.Unlocked;
|
||||
result2P = ConstParameter.ResultOfUnlockUtageJudgement.Unlocked;
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(GameScoreList), "InitalizeUtage")]
|
||||
public static void InitalizeUtage(GameScoreList __instance, int monitorIndex)
|
||||
{
|
||||
if (_needDoublePlayerMusicIdList.Contains(__instance.SessionInfo.musicId))
|
||||
{
|
||||
if (_forceUtageMode == 0)
|
||||
{
|
||||
if (monitorIndex == 0) __instance.SessionInfo.dPScoreFilePathAdd = "_L.ma2";
|
||||
if (monitorIndex == 1) __instance.SessionInfo.dPScoreFilePathAdd = "_R.ma2";
|
||||
}
|
||||
else
|
||||
{
|
||||
__instance.SessionInfo.dPScoreFilePathAdd = _utagePathMap[_forceUtageMode];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(MusicData), "Init")]
|
||||
public static void ForceSetUtagePlayStyle(MusicData __instance)
|
||||
{
|
||||
if(!SinmaiAssist.MainConfig.Cheat.UnlockUtage.UnlockDoublePlayerMusic) return;
|
||||
if (__instance.utagePlayStyle == UtagePlayStyle.DoublePlayerScore)
|
||||
{
|
||||
PropertyInfo utagePlayStyleProperty = typeof(MusicData).GetProperty("utagePlayStyle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
utagePlayStyleProperty.SetValue(__instance, UtagePlayStyle.SinglePlayerScore);
|
||||
_needDoublePlayerMusicIdList.Add(__instance.GetID());
|
||||
#if Debug
|
||||
MelonLogger.Msg($"DoublePlayerScoreLoadEvent: {__instance.GetID()}");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static void SwitchUtageMode()
|
||||
{
|
||||
int current = (int)_forceUtageMode;
|
||||
int next = (current + 1) % 3;
|
||||
_forceUtageMode = (ForceUtageModeType)next;
|
||||
GameMessageManager.SendMessage(0, $"Force Utage Mode: \n{_forceUtageMode.ToString()}");
|
||||
GameMessageManager.SendMessage(1, $"Force Utage Mode: \n{_forceUtageMode.ToString()}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user