Skip to content

Commit

Permalink
feat: PatchShowModsInGameplay
Browse files Browse the repository at this point in the history
  • Loading branch information
rushiiMachine committed Mar 27, 2024
1 parent eb4aace commit ee0e2ca
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 0 deletions.
98 changes: 98 additions & 0 deletions Osu.Patcher.Hook/Patches/PatchShowModsInGameplay.cs
Original file line number Diff line number Diff line change
@@ -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;

/// <summary>
/// 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.
/// </summary>
[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<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> 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,
}
}
20 changes: 20 additions & 0 deletions Osu.Stubs/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,24 @@ public static class Player
Br_S,
}
);

/// <summary>
/// Original: <c>OnLoadComplete(bool success)</c>
/// b20240124: <c>#=zXb_K4cZvV$uy</c>
/// </summary>
[UsedImplicitly]
public static readonly LazyMethod<bool> OnLoadComplete = new(
"Player#OnLoadComplete(...)",
new[]
{
Br,
Ldloc_S,
Callvirt,
Unbox_Any,
Stloc_2,
Ldsfld,
Ldfld,
Call,
}
);
}

0 comments on commit ee0e2ca

Please sign in to comment.