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(); string bulletType = "Normal"; TMP_Text value3 = Traverse.Create(value).Field("bulletTypeText").GetValue(); 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(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(); 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(); } } private static void Postfix(object __instance, int __state) { if (__instance == null) { return; } int num = Traverse.Create(__instance).Property("TotalBulletsFired", (object[])null).GetValue() - __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 AmmoPools { get; } = new Dictionary(); public static Dictionary CurrentAmmo { get; } = new Dictionary(); 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 CachedAmmoStrings { get; } = new Dictionary(); 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 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 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(); 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(); 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 num = obj.Property("MaxAmmo", (object[])null).GetValue() - value; if (amount >= num && num > 0) { foreach (KeyValuePair 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 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 value2 = val.Property("MaxAmmo", (object[])null).GetValue(); 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; } } } } }