上传文件至 Cheat

This commit is contained in:
2025-10-13 18:18:32 +08:00
parent dc6087211e
commit 535e955faf
12 changed files with 1334 additions and 0 deletions

102
Cheat/AllCollection.cs Normal file
View 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
View 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
View 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
View 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;
}
}

View 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}");
}
}
}
}

View 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;
}
}

View 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;
}
}

View 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
View 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
View 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
View 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
View 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()}");
}
}