using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Reptile;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("InfiniteManual")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("InfiniteManual")]
[assembly: AssemblyTitle("InfiniteManual")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace InfiniteManual;
internal static class ManualPatches
{
internal const int TotalPatches = 3;
private static ManualLogSource log;
private static FieldRef<Player, Ability> abilityRef;
private static FieldRef<Player, SlideAbility> slideAbilityRef;
private static FieldRef<Player, bool> isAIRef;
private static FieldRef<Player, GameplayUI> uiRef;
private static FieldRef<Player, float> showLastScoreTimerRef;
private static readonly HashSet<string> reportedErrors = new HashSet<string>();
internal static int Apply(Harmony harmony, ManualLogSource logger)
{
log = logger;
try
{
abilityRef = AccessTools.FieldRefAccess<Player, Ability>("ability");
slideAbilityRef = AccessTools.FieldRefAccess<Player, SlideAbility>("slideAbility");
isAIRef = AccessTools.FieldRefAccess<Player, bool>("isAI");
uiRef = AccessTools.FieldRefAccess<Player, GameplayUI>("ui");
showLastScoreTimerRef = AccessTools.FieldRefAccess<Player, float>("showLastScoreTimer");
}
catch (Exception ex)
{
log.LogError((object)("Could not resolve required Player fields (game update changed them?). No patches applied; the game runs unmodified. Details: " + ex));
return 0;
}
int num = 0;
bool num2 = TryPatch(harmony, typeof(SlideAbility), "FixedUpdateAbility", null, "SlideAbility_FixedUpdateAbility_Postfix");
bool flag = TryPatch(harmony, typeof(SlideAbility), "ComboTimeout", "SlideAbility_ComboTimeout_Prefix", null);
bool flag2 = TryPatch(harmony, typeof(Player), "ScoreDisplayUpdate", null, "Player_ScoreDisplayUpdate_Postfix");
if (num2)
{
num++;
}
if (flag)
{
num++;
}
if (flag2)
{
num++;
}
if (!num2)
{
log.LogWarning((object)"Without the FixedUpdateAbility patch the meter will still drain during manuals.");
}
if (!flag)
{
log.LogWarning((object)"Without the ComboTimeout patch a manual can still end when the meter empties.");
}
if (!flag2)
{
log.LogWarning((object)"Without the ScoreDisplayUpdate patch the HUD bar is hidden (vanilla) instead of shown full.");
}
return num;
}
private static bool TryPatch(Harmony harmony, Type type, string methodName, string prefix, string postfix)
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
string text = type.Name + "." + methodName;
try
{
MethodInfo methodInfo = AccessTools.DeclaredMethod(type, methodName, Type.EmptyTypes, (Type[])null);
if (methodInfo == null)
{
log.LogError((object)("Patch FAILED: " + text + "() not found in Assembly-CSharp."));
return false;
}
HarmonyMethod val = ((prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(ManualPatches), prefix, (Type[])null));
HarmonyMethod val2 = ((postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(ManualPatches), postfix, (Type[])null));
harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
log.LogInfo((object)("Patched " + text + " (" + ((prefix != null) ? "prefix" : "postfix") + ")."));
return true;
}
catch (Exception arg)
{
log.LogError((object)$"Patch FAILED: {text}: {arg}");
return false;
}
}
private static bool IsLocalPlayerInManual(Player p)
{
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Invalid comparison between Unknown and I4
if ((Object)(object)p == (Object)null)
{
return false;
}
if (isAIRef.Invoke(p))
{
return false;
}
SlideAbility val = slideAbilityRef.Invoke(p);
if (val == null)
{
return false;
}
if ((object)abilityRef.Invoke(p) != val)
{
return false;
}
if (!val.IsPerformingManual)
{
return false;
}
return (int)val.slideState != 4;
}
private static void SlideAbility_FixedUpdateAbility_Postfix(SlideAbility __instance)
{
try
{
if (InfiniteManualPlugin.KeepMeterFull && __instance != null)
{
Player p = ((Ability)__instance).p;
if (IsLocalPlayerInManual(p))
{
p.RefillComboTimeOut();
}
}
}
catch (Exception e)
{
ReportOnce("FixedUpdateAbility", e);
}
}
private static bool SlideAbility_ComboTimeout_Prefix(SlideAbility __instance)
{
try
{
if (!InfiniteManualPlugin.Active || __instance == null)
{
return true;
}
if (IsLocalPlayerInManual(((Ability)__instance).p))
{
return false;
}
}
catch (Exception e)
{
ReportOnce("ComboTimeout", e);
}
return true;
}
private static void Player_ScoreDisplayUpdate_Postfix(Player __instance)
{
try
{
if (!InfiniteManualPlugin.KeepMeterFull || !IsLocalPlayerInManual(__instance) || showLastScoreTimerRef.Invoke(__instance) > 0f || !__instance.IsComboing())
{
return;
}
GameplayUI val = uiRef.Invoke(__instance);
if (!((Object)(object)val == (Object)null))
{
if ((Object)(object)val.comboTimeOutBar != (Object)null)
{
val.comboTimeOutBar.fillAmount = 1f;
}
if ((Object)(object)val.comboTimeOutBackdrop != (Object)null)
{
val.comboTimeOutBackdrop.fillAmount = 1f;
}
}
}
catch (Exception e)
{
ReportOnce("ScoreDisplayUpdate", e);
}
}
private static void ReportOnce(string where, Exception e)
{
if (reportedErrors.Add(where))
{
ManualLogSource obj = log;
if (obj != null)
{
obj.LogError((object)$"Exception in {where} patch (further errors from this patch are suppressed): {e}");
}
}
}
}
[BepInPlugin("brc.infinitemanual", "InfiniteManual", "1.0.0")]
[BepInProcess("Bomb Rush Cyberfunk.exe")]
public sealed class InfiniteManualPlugin : BaseUnityPlugin
{
public const string PluginGuid = "brc.infinitemanual";
public const string PluginName = "InfiniteManual";
public const string PluginVersion = "1.0.0";
internal static ManualLogSource Log;
internal static ConfigEntry<bool> EnabledConfig;
internal static ConfigEntry<bool> KeepMeterFullConfig;
internal static ConfigEntry<KeyboardShortcut> ToggleKeyConfig;
internal static bool RuntimeEnabled;
private Harmony harmony;
private string toastText;
private float toastUntil;
internal static bool Active => RuntimeEnabled;
internal static bool KeepMeterFull
{
get
{
if (RuntimeEnabled && KeepMeterFullConfig != null)
{
return KeepMeterFullConfig.Value;
}
return false;
}
}
private void Awake()
{
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Expected O, but got Unknown
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
Log = ((BaseUnityPlugin)this).Logger;
EnabledConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Mod is on when the game starts.");
KeepMeterFullConfig = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "KeepMeterFull", true, "Keep the manual meter full.");
ToggleKeyConfig = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)287, Array.Empty<KeyCode>()), "Key to turn the mod on/off.");
RuntimeEnabled = EnabledConfig.Value;
EnabledConfig.SettingChanged += delegate
{
SetEnabled(EnabledConfig.Value, "config");
};
harmony = new Harmony("brc.infinitemanual");
int num = ManualPatches.Apply(harmony, Log);
Log.LogInfo((object)(string.Format("{0} {1} loaded: {2}/{3} patches applied. ", "InfiniteManual", "1.0.0", num, 3) + $"Enabled={RuntimeEnabled}, KeepMeterFull={KeepMeterFullConfig.Value}, ToggleKey={ToggleKeyConfig.Value}"));
}
private void Update()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
if (ToggleKeyConfig != null)
{
KeyboardShortcut value = ToggleKeyConfig.Value;
if (((KeyboardShortcut)(ref value)).IsDown())
{
SetEnabled(!RuntimeEnabled, "hotkey");
}
}
}
private void SetEnabled(bool value, string source)
{
if (RuntimeEnabled != value)
{
RuntimeEnabled = value;
string text = "InfiniteManual " + (value ? "ON" : "OFF");
Log.LogInfo((object)(text + " (via " + source + ")"));
toastText = text;
toastUntil = Time.unscaledTime + 2f;
}
}
private void OnGUI()
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
if (toastText != null && !(Time.unscaledTime > toastUntil))
{
GUI.Label(new Rect(20f, 20f, 400f, 30f), toastText);
}
}
private void OnDestroy()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
}
}