using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("LimitBypassMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Bypasses integer limits using BigInteger shadow state.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("LimitBypassMod")]
[assembly: AssemblyTitle("LimitBypassMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace LimitBypassMod
{
[HarmonyPatch]
public static class HudMagazineViewController_RenderMagazine_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("HudMagazineViewController"), "RenderMagazine", (Type[])null, (Type[])null);
}
private static void Postfix(object __instance)
{
if (__instance == null)
{
return;
}
object value = Traverse.Create(__instance).Field("view").GetValue();
if (value == null)
{
return;
}
GameObject value2 = Traverse.Create(value).Field("visibilityRoot").GetValue<GameObject>();
string bulletType = "Normal";
TMP_Text value3 = Traverse.Create(value).Field("bulletTypeText").GetValue<TMP_Text>();
if ((Object)(object)value3 != (Object)null && !string.IsNullOrEmpty(value3.text))
{
string text = value3.text.ToUpper();
if (text.Contains("RAINBOW"))
{
bulletType = "Rainbow";
}
else if (text.Contains("SHINY"))
{
bulletType = "Shiny";
}
else if (text.Contains("SILVER"))
{
bulletType = "Silver";
}
else if (text.Contains("EXPLOSIVE"))
{
bulletType = "Explosive";
}
else if (text.Contains("RICOCHET"))
{
bulletType = "Ricochet";
}
else if (text.Contains("CLONE"))
{
bulletType = "Clone";
}
else if (text.Contains("GUARDIAN"))
{
bulletType = "Guardian";
}
}
if (!((Object)(object)value2 != (Object)null))
{
return;
}
TMP_Text[] componentsInChildren = value2.GetComponentsInChildren<TMP_Text>(true);
foreach (TMP_Text val in componentsInChildren)
{
if (long.TryParse(val.text.Replace(" ", "").Replace(".", ""), out var _))
{
val.text = StringFormatter.Instance.GetAmmoString(bulletType);
}
}
}
}
public static class LimitBypassDecisionAPI
{
public static bool CanAffordCurrency(int basePrice, int multiplier = 1)
{
BigInteger bigInteger = new BigInteger(basePrice) * new BigInteger(multiplier);
return ShadowState.Currency >= bigInteger;
}
public static void ConsumeCurrency(int basePrice, int multiplier = 1)
{
BigInteger bigInteger = new BigInteger(basePrice) * new BigInteger(multiplier);
if (ShadowState.Currency >= bigInteger)
{
ShadowState.Currency -= bigInteger;
}
}
}
[BepInPlugin("com.luckyshot.limitbypass", "Limit Bypass Mod", "1.3.0")]
public class LimitBypassPlugin : BaseUnityPlugin
{
public const string PluginGuid = "com.luckyshot.limitbypass";
public const string PluginName = "Limit Bypass Mod";
public const string PluginVersion = "1.3.0";
private void Awake()
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin com.luckyshot.limitbypass is loaded!");
new GameObject("LimitBypass_StringFormatter").AddComponent<StringFormatter>();
new Harmony("com.luckyshot.limitbypass").PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Harmony patches applied successfully.");
}
}
[HarmonyPatch]
public static class GameManager_HandleShotFired_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("GameManager"), "HandleShotFired", (Type[])null, (Type[])null);
}
private static void Prefix(object __instance, out int __state)
{
__state = 0;
if (__instance != null)
{
__state = Traverse.Create(__instance).Property("TotalBulletsFired", (object[])null).GetValue<int>();
}
}
private static void Postfix(object __instance, int __state)
{
if (__instance == null)
{
return;
}
int num = Traverse.Create(__instance).Property("TotalBulletsFired", (object[])null).GetValue<int>() - __state;
if (num > 0)
{
ShadowState.TotalBulletsFired += (BigInteger)num;
if (ShadowState.CurrentAmmo.ContainsKey("Rainbow") && ShadowState.CurrentAmmo["Rainbow"] >= num)
{
ShadowState.CurrentAmmo["Rainbow"] -= (BigInteger)num;
ShadowState.IsAmmoDirty = true;
}
else if (ShadowState.CurrentAmmo.ContainsKey("Normal") && ShadowState.CurrentAmmo["Normal"] >= num)
{
ShadowState.CurrentAmmo["Normal"] -= (BigInteger)num;
ShadowState.IsAmmoDirty = true;
}
}
}
}
[HarmonyPatch]
public static class ShopManager_TryBuy_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("ShopManager"), "TryBuy", (Type[])null, (Type[])null);
}
private static bool Prefix(int cost, ref bool __result)
{
if (cost > 1000000)
{
__result = LimitBypassDecisionAPI.CanAffordCurrency(cost);
return false;
}
return true;
}
}
[HarmonyPatch]
public static class Weapon_HasInfiniteAmmo_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("Weapon"), "get_HasInfiniteAmmo", (Type[])null, (Type[])null);
}
private static bool Prefix(ref bool __result)
{
__result = true;
return false;
}
}
public static class ShadowState
{
private static BigInteger _totalTargetsDestroyed = 0;
private static BigInteger _totalBulletsFired = 0;
private static BigInteger _totalScore = 0;
private static BigInteger _currency = 0;
public static bool IsTargetsDirty { get; private set; } = true;
public static bool IsBulletsDirty { get; private set; } = true;
public static bool IsScoreDirty { get; private set; } = true;
public static bool IsCurrencyDirty { get; private set; } = true;
public static BigInteger TotalTargetsDestroyed
{
get
{
return _totalTargetsDestroyed;
}
set
{
_totalTargetsDestroyed = value;
IsTargetsDirty = true;
}
}
public static BigInteger TotalBulletsFired
{
get
{
return _totalBulletsFired;
}
set
{
_totalBulletsFired = value;
IsBulletsDirty = true;
}
}
public static BigInteger TotalScore
{
get
{
return _totalScore;
}
set
{
_totalScore = value;
IsScoreDirty = true;
}
}
public static BigInteger Currency
{
get
{
return _currency;
}
set
{
_currency = value;
IsCurrencyDirty = true;
}
}
public static Dictionary<string, BigInteger> AmmoPools { get; } = new Dictionary<string, BigInteger>();
public static Dictionary<string, BigInteger> CurrentAmmo { get; } = new Dictionary<string, BigInteger>();
public static bool IsAmmoDirty { get; set; } = true;
public static void ClearTargetsDirty()
{
IsTargetsDirty = false;
}
public static void ClearBulletsDirty()
{
IsBulletsDirty = false;
}
public static void ClearScoreDirty()
{
IsScoreDirty = false;
}
public static void ClearCurrencyDirty()
{
IsCurrencyDirty = false;
}
public static void ResetState()
{
TotalTargetsDestroyed = 0;
TotalBulletsFired = 0;
TotalScore = 0;
Currency = 0;
AmmoPools.Clear();
CurrentAmmo.Clear();
IsAmmoDirty = true;
}
}
public class StringFormatter : MonoBehaviour
{
public static StringFormatter Instance { get; private set; }
public string CachedTargetsString { get; private set; } = "0";
public string CachedBulletsString { get; private set; } = "0";
public string CachedScoreString { get; private set; } = "0";
public string CachedCurrencyString { get; private set; } = "0";
public Dictionary<string, string> CachedAmmoStrings { get; } = new Dictionary<string, string>();
private void Awake()
{
if ((Object)(object)Instance != (Object)null)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
return;
}
Instance = this;
Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
FormatAll();
}
private void LateUpdate()
{
if (ShadowState.IsTargetsDirty)
{
CachedTargetsString = FormatBigInt(ShadowState.TotalTargetsDestroyed);
ShadowState.ClearTargetsDirty();
}
if (ShadowState.IsBulletsDirty)
{
CachedBulletsString = FormatBigInt(ShadowState.TotalBulletsFired);
ShadowState.ClearBulletsDirty();
}
if (ShadowState.IsScoreDirty)
{
CachedScoreString = FormatBigInt(ShadowState.TotalScore);
ShadowState.ClearScoreDirty();
}
if (ShadowState.IsCurrencyDirty)
{
CachedCurrencyString = FormatBigInt(ShadowState.Currency);
ShadowState.ClearCurrencyDirty();
}
if (!ShadowState.IsAmmoDirty)
{
return;
}
CachedAmmoStrings.Clear();
foreach (KeyValuePair<string, BigInteger> item in ShadowState.CurrentAmmo)
{
CachedAmmoStrings[item.Key] = FormatBigInt(item.Value);
}
ShadowState.IsAmmoDirty = false;
}
public void FormatAll()
{
CachedTargetsString = FormatBigInt(ShadowState.TotalTargetsDestroyed);
CachedBulletsString = FormatBigInt(ShadowState.TotalBulletsFired);
CachedScoreString = FormatBigInt(ShadowState.TotalScore);
CachedCurrencyString = FormatBigInt(ShadowState.Currency);
CachedAmmoStrings.Clear();
foreach (KeyValuePair<string, BigInteger> item in ShadowState.CurrentAmmo)
{
CachedAmmoStrings[item.Key] = FormatBigInt(item.Value);
}
ShadowState.IsAmmoDirty = false;
}
public string GetAmmoString(string bulletType)
{
if (CachedAmmoStrings.TryGetValue(bulletType, out var value))
{
return value;
}
return "0";
}
private string FormatBigInt(BigInteger value)
{
if (value > new BigInteger(1000000000000000000L))
{
return value.ToString("E3");
}
return value.ToString("N0");
}
}
[HarmonyPatch]
public static class TMP_Text_set_text_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.PropertySetter(typeof(TMP_Text), "text");
}
private static void Postfix(TMP_Text __instance)
{
if ((Object)(object)__instance != (Object)null && !string.IsNullOrEmpty(__instance.text) && __instance.text.Length > 9 && (__instance.text.Contains("B") || __instance.text.Contains("E") || __instance.text.Length > 12))
{
__instance.enableAutoSizing = true;
if (__instance.fontSizeMin > 10f)
{
__instance.fontSizeMin = 5f;
}
__instance.textWrappingMode = (TextWrappingModes)0;
__instance.overflowMode = (TextOverflowModes)3;
}
}
}
[HarmonyPatch]
public static class ShopMoneyView_SetDisplayedAmount_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("ShopMoneyViewController"), "SetDisplayedAmount", (Type[])null, (Type[])null);
}
[HarmonyPostfix]
private static void Postfix(object __instance)
{
if (__instance == null || !((Object)(object)StringFormatter.Instance != (Object)null))
{
return;
}
object value = Traverse.Create(__instance).Field("view").GetValue();
Component val = (Component)((value is Component) ? value : null);
if (val != null)
{
TMP_Text componentInChildren = val.GetComponentInChildren<TMP_Text>();
if ((Object)(object)componentInChildren != (Object)null)
{
componentInChildren.text = StringFormatter.Instance.CachedCurrencyString;
}
}
}
}
[HarmonyPatch]
public static class TicketView_SetDisplayedAmount_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("TicketViewController"), "SetDisplayedAmount", (Type[])null, (Type[])null);
}
[HarmonyPostfix]
private static void Postfix(object __instance)
{
if (__instance == null || !((Object)(object)StringFormatter.Instance != (Object)null))
{
return;
}
object value = Traverse.Create(__instance).Field("barView").GetValue();
Component val = (Component)((value is Component) ? value : null);
if (val != null)
{
TMP_Text componentInChildren = val.GetComponentInChildren<TMP_Text>();
if ((Object)(object)componentInChildren != (Object)null)
{
componentInChildren.text = StringFormatter.Instance.CachedTargetsString;
}
}
}
}
[HarmonyPatch]
public static class HudMagazineView_SetCountText_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("HudMagazineView"), "SetCountText", (Type[])null, (Type[])null);
}
[HarmonyPostfix]
private static void Postfix(object __instance)
{
if (__instance == null || !((Object)(object)StringFormatter.Instance != (Object)null))
{
return;
}
object value = Traverse.Create(__instance).Field("bulletTypeText").GetValue();
object value2 = Traverse.Create(__instance).Field("bulletCountText").GetValue();
TMP_Text val = (TMP_Text)((value is TMP_Text) ? value : null);
if (val == null)
{
return;
}
TMP_Text val2 = (TMP_Text)((value2 is TMP_Text) ? value2 : null);
if (val2 != null)
{
string bulletType = "Normal";
if (val.text != null && val.text.Contains("Rainbow"))
{
bulletType = "Rainbow";
}
val2.text = StringFormatter.Instance.GetAmmoString(bulletType);
}
}
}
[HarmonyPatch]
public static class Weapon_AddNormalBullets_Patch
{
public static bool IsModRefilling;
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("Weapon"), "AddNormalBulletsToMagazine", (Type[])null, (Type[])null);
}
private static void Prefix(object __instance, int amount)
{
if (IsModRefilling || __instance == null)
{
return;
}
Traverse obj = Traverse.Create(__instance);
int value = obj.Property("CurrentAmmo", (object[])null).GetValue<int>();
int num = obj.Property("MaxAmmo", (object[])null).GetValue<int>() - value;
if (amount >= num && num > 0)
{
foreach (KeyValuePair<string, BigInteger> ammoPool in ShadowState.AmmoPools)
{
ShadowState.CurrentAmmo[ammoPool.Key] = ammoPool.Value;
}
}
else
{
if (ShadowState.CurrentAmmo.ContainsKey("Normal"))
{
ShadowState.CurrentAmmo["Normal"] += (BigInteger)amount;
if (ShadowState.CurrentAmmo["Normal"] > ShadowState.AmmoPools["Normal"])
{
ShadowState.CurrentAmmo["Normal"] = ShadowState.AmmoPools["Normal"];
}
}
foreach (KeyValuePair<string, BigInteger> ammoPool2 in ShadowState.AmmoPools)
{
if (ammoPool2.Key != "Normal")
{
ShadowState.CurrentAmmo[ammoPool2.Key] = ammoPool2.Value;
}
}
}
ShadowState.IsAmmoDirty = true;
}
}
[HarmonyPatch]
public static class Weapon_Update_Patch
{
private static MethodBase TargetMethod()
{
return AccessTools.Method(AccessTools.TypeByName("Weapon"), "Update", (Type[])null, (Type[])null);
}
private static void Postfix(object __instance)
{
if (__instance == null)
{
return;
}
Traverse val = Traverse.Create(__instance);
int value = val.Property("CurrentAmmo", (object[])null).GetValue<int>();
int value2 = val.Property("MaxAmmo", (object[])null).GetValue<int>();
if (value >= value2)
{
return;
}
bool flag = false;
foreach (BigInteger value3 in ShadowState.CurrentAmmo.Values)
{
if (value3 > 0L)
{
flag = true;
break;
}
}
if (flag)
{
int num = value2 - value;
Weapon_AddNormalBullets_Patch.IsModRefilling = true;
try
{
val.Method("AddNormalBulletsToMagazine", new object[1] { num }).GetValue();
}
finally
{
Weapon_AddNormalBullets_Patch.IsModRefilling = false;
}
}
}
}
}