From ee0e2ca9005bd1a0cc0695e41f22d328835c3ee9 Mon Sep 17 00:00:00 2001
From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com>
Date: Wed, 27 Mar 2024 01:30:16 -0700
Subject: [PATCH] feat: PatchShowModsInGameplay
---
.../Patches/PatchShowModsInGameplay.cs | 98 +++++++++++++++++++
Osu.Stubs/Player.cs | 20 ++++
2 files changed, 118 insertions(+)
create mode 100644 Osu.Patcher.Hook/Patches/PatchShowModsInGameplay.cs
diff --git a/Osu.Patcher.Hook/Patches/PatchShowModsInGameplay.cs b/Osu.Patcher.Hook/Patches/PatchShowModsInGameplay.cs
new file mode 100644
index 0000000..3512477
--- /dev/null
+++ b/Osu.Patcher.Hook/Patches/PatchShowModsInGameplay.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using HarmonyLib;
+using JetBrains.Annotations;
+using Osu.Stubs;
+using static System.Reflection.Emit.OpCodes;
+
+namespace Osu.Patcher.Hook.Patches;
+
+///
+/// Makes the mods list overlay that is shown when entering play mode always show, like in a replay
+/// but faded to a user customizable amount.
+///
+[HarmonyPatch]
+[UsedImplicitly]
+public class PatchShowModsInGameplay
+{
+ // TODO: make this user configurable
+ private const float ModsNewAlpha = .2f;
+
+ [UsedImplicitly]
+ [HarmonyTargetMethod]
+ private static MethodBase Target() => Player.OnLoadComplete.Reference;
+
+ [UsedImplicitly]
+ [HarmonyTranspiler]
+ private static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ // Replace a "0f" representing a fade target value after an arbitrary "94f" constant
+ // Also set the pSprite parameter "alwaysDraw" to true
+
+ var replaceState = ReplaceState.Find;
+
+ return instructions.Manipulator(
+ inst =>
+ {
+ switch (replaceState)
+ {
+ case ReplaceState.Find when inst.Is(Ldc_R4, 94f):
+ replaceState = ReplaceState.ReplaceAlwaysDraw;
+ return false;
+
+ // This is calling "InputManager.get_ReplayMode()"
+ case ReplaceState.ReplaceAlwaysDraw when inst.opcode == Call:
+ return true;
+
+ // This is loading the transformation fade end value
+ case ReplaceState.ReplaceFadeEndValue when inst.Is(Ldc_R4, 0f):
+ return true;
+
+ case ReplaceState.Finished:
+ default:
+ return false;
+ }
+ },
+ inst =>
+ {
+ switch (replaceState)
+ {
+ case ReplaceState.ReplaceAlwaysDraw:
+ inst.opcode = Ldc_I4_1; // Load "true" for the parameter "alwaysDraw"
+ inst.operand = null;
+ replaceState = ReplaceState.ReplaceFadeEndValue;
+ break;
+ case ReplaceState.ReplaceFadeEndValue:
+ inst.operand = ModsNewAlpha;
+ replaceState = ReplaceState.Finished;
+ break;
+ case ReplaceState.Find:
+ case ReplaceState.Finished:
+ default:
+ throw new Exception();
+ }
+ }
+ );
+ }
+
+ [UsedImplicitly]
+ [HarmonyFinalizer]
+ [SuppressMessage("ReSharper", "InconsistentNaming")]
+ private static void Finalizer(Exception? __exception)
+ {
+ if (__exception != null)
+ {
+ Console.WriteLine($"Exception due to {nameof(PatchShowModsInGameplay)}: {__exception}");
+ }
+ }
+
+ private enum ReplaceState
+ {
+ Find,
+ ReplaceAlwaysDraw,
+ ReplaceFadeEndValue,
+ Finished,
+ }
+}
\ No newline at end of file
diff --git a/Osu.Stubs/Player.cs b/Osu.Stubs/Player.cs
index 8cb0041..85691d6 100644
--- a/Osu.Stubs/Player.cs
+++ b/Osu.Stubs/Player.cs
@@ -33,4 +33,24 @@ public static class Player
Br_S,
}
);
+
+ ///
+ /// Original: OnLoadComplete(bool success)
+ /// b20240124: #=zXb_K4cZvV$uy
+ ///
+ [UsedImplicitly]
+ public static readonly LazyMethod OnLoadComplete = new(
+ "Player#OnLoadComplete(...)",
+ new[]
+ {
+ Br,
+ Ldloc_S,
+ Callvirt,
+ Unbox_Any,
+ Stloc_2,
+ Ldsfld,
+ Ldfld,
+ Call,
+ }
+ );
}
\ No newline at end of file