Decompiled source of MoreShopUpgrades v1.4.1
MorePots.dll
Decompiled 10 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using Assets.Scripts.Actors; using Assets.Scripts.Actors.Enemies; using Assets.Scripts.Actors.Player; using Assets.Scripts.Game.Combat.ConstantAttacks; using Assets.Scripts.Game.MapGeneration; using Assets.Scripts.Inventory__Items__Pickups; using Assets.Scripts.Inventory__Items__Pickups.GoldAndMoney; using Assets.Scripts.Inventory__Items__Pickups.Interactables; using Assets.Scripts.Inventory__Items__Pickups.Items; using Assets.Scripts.Inventory__Items__Pickups.Items.ItemImplementations; using Assets.Scripts.Inventory__Items__Pickups.Stats; using Assets.Scripts.Inventory__Items__Pickups.Weapons; using Assets.Scripts.Inventory__Items__Pickups.Weapons.Projectiles; using Assets.Scripts.Managers; using Assets.Scripts.Menu.Shop; using Assets.Scripts.Saves___Serialization.Progression; using Assets.Scripts.Saves___Serialization.Progression.Achievements; using Assets.Scripts.Saves___Serialization.SaveFiles; using Assets.Scripts.Saves___Serialization.SaveFiles.Configs; using Assets.Scripts.Saves___Serialization.SaveFiles.Configs.ConfigSettingsTypes; using Assets.Scripts.Settings___Saves.SaveFiles; using Assets.Scripts.Settings___Saves.SaveFiles.ConfigSaves; using Assets.Scripts.Settings___Saves.SaveFiles.ConfigSettingsTypes; using Assets.Scripts.UI.InGame.Rewards; using Assets.Scripts.Utility; using Assets.Scripts._Data; using Assets.Scripts._Data.ShopItems; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Common; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using Inventory__Items__Pickups.Pickups; using Microsoft.CodeAnalysis; using Rewired; using TMPro; using UnityEngine; using UnityEngine.Audio; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("MorePots")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.38.0.0")] [assembly: AssemblyInformationalVersion("0.38.0+9583c9456c88608702ad5b96818742c7ac815822")] [assembly: AssemblyProduct("MorePots")] [assembly: AssemblyTitle("MorePots")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.38.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 MorePots { internal static class AuraTint { private class Tinted { internal readonly List<Renderer> renderers = new List<Renderer>(); internal readonly List<MaterialPropertyBlock> saved = new List<MaterialPropertyBlock>(); internal readonly List<ParticleSystem> particles = new List<ParticleSystem>(); internal readonly List<MinMaxGradient> savedStart = new List<MinMaxGradient>(); internal CombatAura combatAura; internal Color[] savedDefaults; internal bool on; } internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<string> TintColor; private static readonly Dictionary<IntPtr, Tinted> byWeapon = new Dictionary<IntPtr, Tinted>(); private static float nextScan; private static readonly int[] colorIds = new int[5] { Shader.PropertyToID("_Tint"), Shader.PropertyToID("_Color"), Shader.PropertyToID("_TintColor"), Shader.PropertyToID("_BaseColor"), Shader.PropertyToID("_MainColor") }; private static readonly Dictionary<IntPtr, bool> wasActive = new Dictionary<IntPtr, bool>(); private static string lastScanReport; internal static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("ManualFire", "PassiveIdleTint", true, "Passive weapons' effect is tinted (gray) while not triggered, and shows its normal colour while triggered or while holding with Auto Fire."); TintColor = config.Bind<string>("ManualFire", "PassiveIdleColor", "#7A7A7AFF", "Tint colour for passive weapons while not triggered, as #RRGGBB or #RRGGBBAA."); } internal static void Tick(List<WeaponBase> alwaysOnSelected, bool holdingAuto) { PassiveFx.SetHum(holdingAuto && alwaysOnSelected.Count > 0); if (!Enabled.Value) { return; } float unscaledTime = Time.unscaledTime; if (unscaledTime >= nextScan) { nextScan = unscaledTime + 2f; Scan(); } foreach (KeyValuePair<IntPtr, Tinted> kv in byWeapon) { WeaponBase val = null; foreach (WeaponBase item in AllAlwaysOn()) { if (((Il2CppObjectBase)item).Pointer == kv.Key) { val = item; break; } } bool flag = val != null && (ManualFire.InFullWindow(val) || (holdingAuto && alwaysOnSelected.Exists((WeaponBase w) => ((Il2CppObjectBase)w).Pointer == kv.Key))); bool flag2 = val != null && !flag; if (flag2 != kv.Value.on) { Set(kv.Value, flag2); } else if (flag2) { Reapply(kv.Value); } } } private static Color Tint() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (!ColorUtility.TryParseHtmlString(TintColor.Value, ref result)) { return new Color(0.48f, 0.48f, 0.48f, 1f); } return result; } internal static void Clear() { wasActive.Clear(); foreach (Tinted value in byWeapon.Values) { if (value.on) { Set(value, on: false); } } byWeapon.Clear(); } private static List<WeaponBase> AllAlwaysOn() { List<WeaponBase> list = new List<WeaponBase>(); MyPlayer instance = MyPlayer.Instance; object obj; if (instance == null) { obj = null; } else { PlayerInventory inventory = instance.inventory; obj = ((inventory != null) ? inventory.weaponInventory : null); } WeaponInventory val = (WeaponInventory)obj; if (val == null) { return list; } Enumerator<EWeapon, WeaponBase> enumerator = val.weapons.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair<EWeapon, WeaponBase> current = enumerator.Current; if (ManualFire.IsAlwaysOn(current.Value)) { list.Add(current.Value); } } return list; } private static void Scan() { //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Expected O, but got Unknown //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Expected O, but got Unknown //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Expected O, but got Unknown Il2CppArrayBase<ConstantAttack> val = Object.FindObjectsOfType<ConstantAttack>(true); List<string> list = new List<string>(); foreach (ConstantAttack item in val) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 4); defaultInterpolatedStringHandler.AppendFormatted(((MemberInfo)((Object)item).GetIl2CppType()).Name); defaultInterpolatedStringHandler.AppendLiteral(":"); WeaponBase weaponBase = item.weaponBase; defaultInterpolatedStringHandler.AppendFormatted(((Object)(object)((weaponBase != null) ? weaponBase.weaponData : null) != (Object)null) ? ((object)item.weaponBase.weaponData.eWeapon/*cast due to .constrained prefix*/).ToString() : "no weapon"); defaultInterpolatedStringHandler.AppendLiteral(":"); defaultInterpolatedStringHandler.AppendFormatted(((Component)item).gameObject.activeInHierarchy ? "active" : "inactive"); defaultInterpolatedStringHandler.AppendLiteral(":"); defaultInterpolatedStringHandler.AppendFormatted((item.weaponBase != null && ManualFire.IsAlwaysOn(item.weaponBase)) ? "passive" : "-"); list.Add(defaultInterpolatedStringHandler.ToStringAndClear()); } string text = string.Join(", ", list); bool flag = default(bool); if (text != lastScanReport) { lastScanReport = text; ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(43, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Aura tint: scan found "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val.Length); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" constant attack(s): "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); } log.LogInfo(val2); } foreach (ConstantAttack item2 in val) { WeaponBase weaponBase2 = item2.weaponBase; if (weaponBase2 == null || !ManualFire.IsAlwaysOn(weaponBase2) || byWeapon.ContainsKey(((Il2CppObjectBase)weaponBase2).Pointer)) { continue; } Tinted tinted = new Tinted(); foreach (Renderer componentsInChild in ((Component)item2).gameObject.GetComponentsInChildren<Renderer>(true)) { tinted.renderers.Add(componentsInChild); MaterialPropertyBlock val3 = new MaterialPropertyBlock(); componentsInChild.GetPropertyBlock(val3); tinted.saved.Add(val3); } foreach (ParticleSystem componentsInChild2 in ((Component)item2).gameObject.GetComponentsInChildren<ParticleSystem>(true)) { tinted.particles.Add(componentsInChild2); tinted.savedStart.Add(componentsInChild2.main.startColor); } tinted.combatAura = ((Component)item2).gameObject.GetComponent<CombatAura>(); byWeapon[((Il2CppObjectBase)weaponBase2).Pointer] = tinted; ManualLogSource log2 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(73, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Aura tint: "); BepInExInfoLogInterpolatedStringHandler obj = val2; WeaponData weaponData = weaponBase2.weaponData; ((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<EWeapon?>((weaponData != null) ? new EWeapon?(weaponData.eWeapon) : ((EWeapon?)null)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" has "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(tinted.renderers.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" renderer(s), "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(tinted.particles.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" particle system(s), combat aura colours: "); BepInExInfoLogInterpolatedStringHandler obj2 = val2; CombatAura combatAura = tinted.combatAura; ((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<int>((((combatAura != null) ? combatAura.defaultColors : null) != null) ? ((Il2CppArrayBase<Color>)(object)tinted.combatAura.defaultColors).Length : 0); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log2.LogInfo(val2); foreach (Renderer renderer in tinted.renderers) { Material val4 = ((renderer != null) ? renderer.sharedMaterial : null); if ((Object)(object)((val4 != null) ? val4.shader : null) == (Object)null) { continue; } List<string> list2 = new List<string>(); for (int i = 0; i < val4.shader.GetPropertyCount(); i++) { if ((int)val4.shader.GetPropertyType(i) == 0) { list2.Add(val4.shader.GetPropertyName(i)); } } ManualLogSource log3 = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(46, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Aura tint: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)renderer).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": shader '"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)val4.shader).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("', colour properties ["); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(string.Join(", ", list2)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]"); } log3.LogInfo(val2); } } } private static void Reapply(Tinted t) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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) //IL_002c: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) Color val = Tint(); foreach (Renderer renderer in t.renderers) { if (!((Object)(object)renderer == (Object)null)) { MaterialPropertyBlock val2 = new MaterialPropertyBlock(); renderer.GetPropertyBlock(val2); int[] array = colorIds; foreach (int num in array) { val2.SetColor(num, val); } renderer.SetPropertyBlock(val2); } } CombatAura combatAura = t.combatAura; Il2CppStructArray<Color> val3 = ((combatAura != null) ? combatAura.defaultColors : null); if (val3 != null) { for (int j = 0; j < ((Il2CppArrayBase<Color>)(object)val3).Length; j++) { ((Il2CppArrayBase<Color>)(object)val3)[j] = new Color(val.r, val.g, val.b, ((Il2CppArrayBase<Color>)(object)val3)[j].a); } } } private static void Set(Tinted t, bool on) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) t.on = on; for (int i = 0; i < t.renderers.Count; i++) { Renderer val = t.renderers[i]; if ((Object)(object)val == (Object)null) { continue; } if (on) { MaterialPropertyBlock val2 = new MaterialPropertyBlock(); val.GetPropertyBlock(val2); t.saved[i] = val2; MaterialPropertyBlock val3 = new MaterialPropertyBlock(); val.GetPropertyBlock(val3); int[] array = colorIds; foreach (int num in array) { val3.SetColor(num, Tint()); } val.SetPropertyBlock(val3); } else { val.SetPropertyBlock(t.saved[i]); } } Color val4 = Tint(); CombatAura combatAura = t.combatAura; Il2CppStructArray<Color> val5 = ((combatAura != null) ? combatAura.defaultColors : null); if (val5 == null) { return; } if (on) { t.savedDefaults = (Color[])(object)new Color[((Il2CppArrayBase<Color>)(object)val5).Length]; for (int k = 0; k < ((Il2CppArrayBase<Color>)(object)val5).Length; k++) { t.savedDefaults[k] = ((Il2CppArrayBase<Color>)(object)val5)[k]; ((Il2CppArrayBase<Color>)(object)val5)[k] = new Color(val4.r, val4.g, val4.b, ((Il2CppArrayBase<Color>)(object)val5)[k].a); } } else if (t.savedDefaults != null) { for (int l = 0; l < ((Il2CppArrayBase<Color>)(object)val5).Length && l < t.savedDefaults.Length; l++) { ((Il2CppArrayBase<Color>)(object)val5)[l] = t.savedDefaults[l]; } } } } internal static class AutoPots { internal enum SilverMode { Fly, Instant, Drop } internal static CustomShopItem Shop; internal static ConfigEntry<float> Radius; internal static ConfigEntry<float> RangeMultiplierPerLevel; internal static ConfigEntry<int> MaxPerCheck; internal static ConfigEntry<SilverMode> Silver; internal static int CoinsSent; internal static int SilverCollected; private static int loggedSent = -1; private static float nextSummary; internal static bool Breaking; private static readonly List<InteractablePot> pots = new List<InteractablePot>(); private static readonly List<(float d2, int index)> inRange = new List<(float, int)>(); private static bool listDirty = true; private static float nextCheck; internal static bool Active => Shop.CurrentLevel > 0; internal static float CurrentRange => RangeAt(Shop.CurrentLevel); internal static void Bind(ConfigFile config, ConfigFile progress) { ConfigEntry<string> prices = config.Bind<string>("AutoPots", "Prices", "200,200,200,200,200,200", "Silver price of each Auto Pots level, comma separated. The count sets the max level."); Radius = config.Bind<float>("AutoPots", "Radius", 4f, "Range at level 1, in world units."); RangeMultiplierPerLevel = config.Bind<float>("AutoPots", "RangeMultiplierPerLevel", 2f, "Each level after the first multiplies the range by this."); Silver = config.Bind<SilverMode>("AutoPots", "SilverFromAutoPots", SilverMode.Fly, "Fly: silver coins from auto-broken pots fly to you from wherever the pot was. Instant: added straight to your silver, no coins. Drop: coins stay where the pot was (the game's default; far ones are rarely collected)."); MaxPerCheck = config.Bind<int>("AutoPots", "MaxPotsPerCheck", 25, "Most pots broken per check (10 checks a second), closest first, so a huge range can't freeze the game."); Shop = new CustomShopItem(104, "Auto Pots", progress.Bind<int>("Progress", "AutoPotsLevel", 0, "Levels of the Auto Pots shop upgrade bought. Managed by the mod."), () => CustomShopItem.ParsePrices(prices.Value), Description, (string name) => name == "ItemPot"); } internal static float RangeAt(int level) { if (level > 0) { return Radius.Value * MathF.Pow(RangeMultiplierPerLevel.Value, level - 1); } return 0f; } private static string Description() { return $"Pots within range break automatically, no button needed, and their silver flies to you. Each level after the first multiplies the range by {RangeMultiplierPerLevel.Value:0.#}."; } internal static void MarkDirty() { listDirty = true; } private static void LogSummary() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown float unscaledTime = Time.unscaledTime; if (!(unscaledTime < nextSummary) && CoinsSent != loggedSent) { nextSummary = unscaledTime + 10f; loggedSent = CoinsSent; MyPlayer instance = MyPlayer.Instance; object obj; if (instance == null) { obj = null; } else { PlayerInventory inventory = instance.inventory; obj = ((inventory != null) ? inventory.playerStats : null); } PlayerStatsNew val = (PlayerStatsNew)obj; string text = ((val == null) ? "?" : val.GetStat((EStat)49).ToString("0.##")); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(106, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Auto Pots: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(CoinsSent); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" silver coins sent flying to you; "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(SilverCollected); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" silver collected this session (all sources); silver bonus x"); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log.LogInfo(val2); } } internal static void Tick() { //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown if (!Active || MyTime.paused) { return; } LogSummary(); float unscaledTime = Time.unscaledTime; if (unscaledTime < nextCheck) { return; } nextCheck = unscaledTime + 0.1f; MyPlayer instance = MyPlayer.Instance; if ((Object)(object)instance == (Object)null) { return; } if (listDirty) { listDirty = false; pots.Clear(); foreach (InteractablePot item2 in Object.FindObjectsOfType<InteractablePot>()) { if (!item2.broken) { pots.Add(item2); } } ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Auto Pots: tracking "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(pots.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" pots."); } log.LogInfo(val); } Vector3 position = ((Component)instance).transform.position; float currentRange = CurrentRange; float num = currentRange * currentRange; pots.RemoveAll((InteractablePot pot) => (Object)(object)pot == (Object)null || pot.broken); inRange.Clear(); for (int num2 = 0; num2 < pots.Count; num2++) { Vector3 val2 = ((Component)pots[num2]).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude <= num) { inRange.Add((sqrMagnitude, num2)); } } if (inRange.Count == 0) { return; } inRange.Sort(((float d2, int index) a, (float d2, int index) b) => a.d2.CompareTo(b.d2)); int num3 = Math.Min(inRange.Count, Math.Max(1, MaxPerCheck.Value)); List<int> list = new List<int>(num3); for (int num4 = 0; num4 < num3; num4++) { int item = inRange[num4].index; Breaking = true; try { ((BaseInteractable)pots[item]).Interact(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Auto Pots: breaking a pot failed: " + ex.Message)); } finally { Breaking = false; } list.Add(item); } list.Sort(); for (int num5 = list.Count - 1; num5 >= 0; num5--) { pots.RemoveAt(list[num5]); } } } [HarmonyPatch(typeof(RandomObjectPlacer), "RandomObjectSpawner")] internal static class RandomObjectPlacer_RandomObjectSpawner_AutoPots { private static void Postfix() { AutoPots.MarkDirty(); } } [HarmonyPatch(typeof(MyTime), "OnNewStageStarted")] internal static class MyTime_OnNewStageStarted_AutoPots { private static void Postfix() { AutoPots.MarkDirty(); } } [HarmonyPatch(typeof(MyTime), "Update")] internal static class MyTime_Update_AutoPots { private static void Postfix() { AutoPots.Tick(); } } [HarmonyPatch(typeof(MoneyUtility), "SpawnSilverNoTimerImpact")] internal static class MoneyUtility_SpawnSilverNoTimerImpact_AutoPots { private static bool Prefix(int amount) { if (!AutoPots.Breaking || AutoPots.Silver.Value != AutoPots.SilverMode.Instant) { return true; } MyPlayer instance = MyPlayer.Instance; PlayerInventory val = ((instance != null) ? instance.inventory : null); if (val == null) { return true; } val.AddSilver(amount); return false; } } [HarmonyPatch(typeof(SilverFlying), "Set")] internal static class SilverFlying_Set_AutoPots { private static void Postfix(SilverFlying __instance) { if (AutoPots.Breaking && AutoPots.Silver.Value == AutoPots.SilverMode.Fly) { MyPlayer instance = MyPlayer.Instance; if (!((Object)(object)instance == (Object)null)) { __instance.target = ((Component)instance).transform; AutoPots.CoinsSent++; } } } } [HarmonyPatch(typeof(PlayerInventory), "AddSilver")] internal static class PlayerInventory_AddSilver_AutoPots { private static void Postfix(int amount) { AutoPots.SilverCollected += amount; } } internal static class AutoShrineRewards { internal enum PickMode { Best, Random } internal static CustomShopItem Shop; internal static ConfigEntry<PickMode> Mode; internal static ConfigEntry<string> Encounters; internal static ConfigEntry<float> Delay; internal static EEncounter OpenType; internal static float OpenedAt; internal static bool Pending; internal static bool Active => Shop.CurrentLevel > 0; internal static void Bind(ConfigFile config, ConfigFile progress) { Mode = config.Bind<PickMode>("AutoShrineRewards", "Mode", PickMode.Best, "Best: highest rarity offer. Random: any offer."); Encounters = config.Bind<string>("AutoShrineRewards", "Encounters", "RandomStats", "Reward windows to auto-pick, comma separated (RandomStats = charge shrine). The log names each window type as it opens."); Delay = config.Bind<float>("AutoShrineRewards", "DelaySeconds", 0f, "0 = pick instantly, before the window is ever drawn. Above 0: seconds the window stays open (so you can see the offers) before picking."); ConfigEntry<int> price = config.Bind<int>("AutoShrineRewards", "Price", 300, "Silver price of the Auto Shrine Rewards upgrade."); Shop = new CustomShopItem(106, "Auto Shrine Rewards", progress.Bind<int>("Progress", "AutoShrineRewardsLevel", 0, "1 when the Auto Shrine Rewards shop upgrade is owned. Managed by the mod."), () => new int[1] { price.Value }, Description, null); } private static string Description() { return "Free. Charge shrine rewards are picked for you instantly (" + ((Mode.Value == PickMode.Best) ? "highest rarity" : "random") + "). Refund to turn it off."; } internal unsafe static bool Handles(EEncounter type) { string[] array = Encounters.Value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); for (int i = 0; i < array.Length; i++) { if (string.Equals(array[i], ((object)(*(EEncounter*)(&type))/*cast due to .constrained prefix*/).ToString(), StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static int Rank(ERarity r) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Expected I4, but got Unknown if ((int)r != 0) { return (int)r; } return -1; } internal static void TryPick(EncounterUi ui) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if (!Pending || Time.unscaledTime - OpenedAt < Delay.Value) { return; } Pending = false; Il2CppReferenceArray<EncounterOffer> offers = ui.offers; if (offers == null || ((Il2CppArrayBase<EncounterOffer>)(object)offers).Length == 0) { return; } List<int> list = new List<int>(); string text = default(string); for (int i = 0; i < ((Il2CppArrayBase<EncounterOffer>)(object)offers).Length; i++) { EncounterOffer val = ((Il2CppArrayBase<EncounterOffer>)(object)offers)[i]; if (val != null && val.CanAccept(ref text)) { list.Add(i); } } bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2; if (list.Count == 0) { ManualLogSource log = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(64, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Auto Shrine Rewards: no acceptable offer in "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EEncounter>(OpenType); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; leaving it to you."); } log.LogInfo(val2); return; } int num; if (Mode.Value == PickMode.Random) { num = list[Random.Range(0, list.Count)]; } else { num = list[0]; foreach (int item in list) { if (Rank(((Il2CppArrayBase<EncounterOffer>)(object)offers)[item].rarity) > Rank(((Il2CppArrayBase<EncounterOffer>)(object)offers)[num].rarity)) { num = item; } } } ManualLogSource log2 = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(46, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Auto Shrine Rewards: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EEncounter>(OpenType); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" picked offer "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num + 1); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" of "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(((Il2CppArrayBase<EncounterOffer>)(object)offers).Length); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<ERarity>(((Il2CppArrayBase<EncounterOffer>)(object)offers)[num].rarity); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<PickMode>(Mode.Value); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("): "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Il2CppArrayBase<EncounterOffer>)(object)offers)[num].GetEffectsDescription()); } log2.LogInfo(val2); ((BaseEncounterWindow)ui).ChooseOffer(num); } } [HarmonyPatch(typeof(EncounterUi), "Open")] internal static class EncounterUi_Open { private static void Postfix(EncounterUi __instance, EEncounter encounterType) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) bool flag = AutoShrineRewards.Active && AutoShrineRewards.Handles(encounterType); ManualLogSource log = Plugin.Log; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(22, 2, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reward window opened: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<EEncounter>(encounterType); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(flag ? " (auto-pick)" : ""); } log.LogInfo(val); AutoShrineRewards.OpenType = encounterType; AutoShrineRewards.OpenedAt = Time.unscaledTime; AutoShrineRewards.Pending = flag; if (flag && AutoShrineRewards.Delay.Value <= 0f) { try { AutoShrineRewards.TryPick(__instance); } catch (Exception ex) { AutoShrineRewards.Pending = false; Plugin.Log.LogError((object)("Auto Shrine Rewards failed: " + ex)); } } } } [HarmonyPatch(typeof(EncounterUi), "Update")] internal static class EncounterUi_Update { private static void Postfix(EncounterUi __instance) { if (!AutoShrineRewards.Pending) { return; } try { AutoShrineRewards.TryPick(__instance); } catch (Exception ex) { AutoShrineRewards.Pending = false; Plugin.Log.LogError((object)("Auto Shrine Rewards failed: " + ex)); } } } [HarmonyPatch(typeof(EncounterUi), "OnClose")] internal static class EncounterUi_OnClose { private static void Postfix() { AutoShrineRewards.Pending = false; } } internal static class ButtonFit { internal const float SidePadding = 40f; private static readonly HashSet<string> logged = new HashSet<string>(); internal static void Fit(GameObject button, TextMeshProUGUI label) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown RectTransform component = button.GetComponent<RectTransform>(); ((TMP_Text)label).enableAutoSizing = false; ((TMP_Text)label).textWrappingMode = (TextWrappingModes)0; float x = ((TMP_Text)label).GetPreferredValues(((TMP_Text)label).text).x; TextSizer component2 = ((Component)label).gameObject.GetComponent<TextSizer>(); if ((Object)(object)component2 != (Object)null) { if (component2.MaxSize.x > 0f && component2.MaxSize.x < x + component2.Padding.x * 2f) { component2.MaxSize = new Vector2(x + component2.Padding.x * 2f, component2.MaxSize.y); } component2.Refresh(); } ButtonTextWrapper component3 = button.GetComponent<ButtonTextWrapper>(); if (component3 != null) { component3.Refresh(); } float num = x + 80f; LayoutElement obj = button.GetComponent<LayoutElement>() ?? button.AddComponent<LayoutElement>(); obj.minWidth = num; obj.preferredWidth = num; component.SetSizeWithCurrentAnchors((Axis)0, num); if ((Object)(object)button.transform.parent != (Object)null) { LayoutRebuilder.MarkLayoutForRebuild(((Component)button.transform.parent).gameObject.GetComponent<RectTransform>()); } if (logged.Add(((Object)button).name)) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Button '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)button).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': width "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "F0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" for text "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(x, "F0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" + "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(40f, "F0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" padding each side."); } log.LogInfo(val); } } } internal static class ChestSkip { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<KeyCode> ExtraKey; internal static ConfigEntry<KeyCode> ExtraPadButton; internal static bool Forcing; private static bool loggedAction; internal static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("Chests", "JumpSkipsChestAnimation", true, "Press jump to skip the chest opening animation."); ExtraKey = config.Bind<KeyCode>("Chests", "SkipKey", (KeyCode)32, "Keyboard key that also skips (in case jump is disabled while the chest window is open)."); ExtraPadButton = config.Bind<KeyCode>("Chests", "SkipPadButton", (KeyCode)330, "Controller button that also skips (JoystickButton0 = A on Xbox pads)."); } internal static bool JumpPressed() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) bool flag = false; try { flag = MyInputManager.GetButtonDown(MyInputManager.Jump); } catch { } if (!flag && !Input.GetKeyDown(ExtraKey.Value)) { return Input.GetKeyDown(ExtraPadButton.Value); } return true; } internal static void LogForcedAction(string action) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!loggedAction) { loggedAction = true; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Chest skip: chest asked for '"); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(action); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("', answered pressed."); } log.LogInfo(val); } } } [HarmonyPatch(typeof(ChestOpening), "Update")] internal static class ChestOpening_Update { private static void Prefix(ChestOpening __instance) { ChestSkip.Forcing = ChestSkip.Enabled.Value && __instance.canSkip && !__instance.skipped && ChestSkip.JumpPressed(); } private static void Postfix(ChestOpening __instance) { if (ChestSkip.Forcing) { ChestSkip.Forcing = false; if (__instance.skipped) { Plugin.Log.LogInfo((object)"Chest skip: skipped via the game's own skip."); return; } __instance.skipped = true; Plugin.Log.LogInfo((object)"Chest skip: set skipped directly (game didn't ask for a button this frame)."); } } } [HarmonyPatch(typeof(MyInputManager), "GetButtonDown")] internal static class MyInputManager_GetButtonDown { private static void Postfix(string action, ref bool __result) { if (!(!ChestSkip.Forcing | __result)) { __result = true; ChestSkip.LogForcedAction(action); } } } internal class CustomShopItem { internal static readonly List<CustomShopItem> All = new List<CustomShopItem>(); internal readonly EShopItem Id; internal readonly string Title; internal readonly ConfigEntry<int> Level; internal readonly Func<int[]> Prices; internal readonly Func<string> Description; internal readonly Func<string, bool> IconMatch; internal ShopItemData Data; internal Func<int, string> LevelStat; internal int MaxLevel => Prices().Length; internal int CurrentLevel => Math.Clamp(Level.Value, 0, MaxLevel); internal string FullDescription() { string text = Description(); if (LevelStat == null || MaxLevel <= 1) { return text; } List<string> list = new List<string>(); int currentLevel = CurrentLevel; for (int i = 1; i <= MaxLevel; i++) { string text2 = $"Lv{i} {LevelStat(i)}"; if (i == currentLevel) { text2 = "<color=#ffd84d><b>" + text2 + "</b></color>"; } else if (i > currentLevel) { text2 = "<color=#8a8a8a>" + text2 + "</color>"; } list.Add(text2); } return text + "\n" + string.Join(" · ", list); } internal CustomShopItem(int id, string title, ConfigEntry<int> level, Func<int[]> prices, Func<string> description, Func<string, bool> iconMatch) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) Id = (EShopItem)id; Title = title; Level = level; Prices = prices; Description = description; IconMatch = iconMatch; All.Add(this); } internal int LevelPrice(int level) { int[] array = Prices(); return array[Math.Clamp(level, 0, array.Length - 1)]; } internal static void RefundLevelsOverCap() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown SaveManager instance = SaveManager.Instance; ProgressionSaveFile val = ((instance != null) ? instance.progression : null); if (val == null) { return; } bool flag = default(bool); foreach (CustomShopItem item in All) { int value = item.Level.Value; int maxLevel = item.MaxLevel; if (value > maxLevel) { int num = 0; for (int i = maxLevel; i < value; i++) { num += item.LevelPrice(i); } val.AddSilver(num); item.Level.Value = maxLevel; SaveManager.Instance.SaveProgression(); ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(61, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item.Title); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": max level is now "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(maxLevel); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("; refunded "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(value - maxLevel); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" level(s) above it for "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" silver."); } log.LogInfo(val2); } } } internal int RefundAmount() { if (CurrentLevel <= 0) { return 0; } return LevelPrice(CurrentLevel - 1); } internal static CustomShopItem For(EShopItem id) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) foreach (CustomShopItem item in All) { if (item.Id == id) { return item; } } return null; } internal static CustomShopItem For(ShopItemData data) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)data == (Object)null)) { return For(data.eShopItem); } return null; } internal static int[] ParsePrices(string csv) { return Array.ConvertAll(csv.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries), int.Parse); } internal void Register(DataManager dm, ShopItemData template) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown if (!dm.shopItems.ContainsKey(Id)) { ShopItemData val = Object.Instantiate<ShopItemData>(template); ((Object)val).name = "ShopItem_" + Title.Replace(" ", ""); val.eShopItem = Id; val.maxLevel = MaxLevel; val.unlockRequirement = null; val.canRefund = true; val.sortingOrder = template.sortingOrder + 1 + All.IndexOf(this); Object.DontDestroyOnLoad((Object)(object)val); Texture val2 = ((IconMatch == null) ? null : FindTexture(IconMatch)); if ((Object)(object)val2 != (Object)null) { val.icon = val2; } dm.shopItems[Id] = val; dm.unsortedShopItems.Add(val); Data = val; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(47, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("Added '"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(Title); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' shop item (max level "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(MaxLevel); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", level "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(CurrentLevel); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", icon "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)(object)val2 != (Object)null) ? ((Object)val2).name : "from template"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(")."); } log.LogInfo(val3); } } private static Texture FindTexture(Func<string, bool> match) { foreach (Texture2D item in Resources.FindObjectsOfTypeAll<Texture2D>()) { if (match(((Object)item).name)) { return (Texture)(object)item; } } return null; } } [HarmonyPatch(typeof(DataManager), "Load")] internal static class DataManager_Load { private static void Postfix(DataManager __instance) { ShopItemData shopItemData = __instance.GetShopItemData((EShopItem)6); if ((Object)(object)shopItemData == (Object)null) { Plugin.Log.LogWarning((object)"Silver shop item not found; custom shop items not added."); return; } foreach (CustomShopItem item in CustomShopItem.All) { item.Register(__instance, shopItemData); } } } [HarmonyPatch(typeof(ProgressionSaveFile), "GetShopItemLevel")] internal static class Progression_GetShopItemLevel { private static bool Prefix(EShopItem eShopItem, ref int __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) CustomShopItem customShopItem = CustomShopItem.For(eShopItem); if (customShopItem == null) { return true; } __result = customShopItem.CurrentLevel; return false; } } [HarmonyPatch(typeof(ProgressionSaveFile), "HasShopItem")] internal static class Progression_HasShopItem { private static bool Prefix(EShopItem eShopItem, ref bool __result) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) CustomShopItem customShopItem = CustomShopItem.For(eShopItem); if (customShopItem == null) { return true; } __result = customShopItem.CurrentLevel > 0; return false; } } [HarmonyPatch(typeof(ShopItemData), "GetLevel")] internal static class ShopItemData_GetLevel { private static bool Prefix(ShopItemData __instance, ref int __result) { CustomShopItem customShopItem = CustomShopItem.For(__instance); if (customShopItem == null) { return true; } __result = customShopItem.CurrentLevel; return false; } } [HarmonyPatch(typeof(ShopItemData), "GetMaxLevel")] internal static class ShopItemData_GetMaxLevel { private static bool Prefix(ShopItemData __instance, ref int __result) { CustomShopItem customShopItem = CustomShopItem.For(__instance); if (customShopItem == null) { return true; } __result = customShopItem.MaxLevel; return false; } } [HarmonyPatch(typeof(ShopItemData), "IsMaxLevel")] internal static class ShopItemData_IsMaxLevel { private static bool Prefix(ShopItemData __instance, ref bool __result) { CustomShopItem customShopItem = CustomShopItem.For(__instance); if (customShopItem == null) { return true; } __result = customShopItem.CurrentLevel >= customShopItem.MaxLevel; return false; } } [HarmonyPatch(typeof(ShopItemData), "GetLevelPrice")] internal static class ShopItemData_GetLevelPrice { private static bool Prefix(ShopItemData __instance, int level, ref int __result) { CustomShopItem customShopItem = CustomShopItem.For(__instance); if (customShopItem == null) { return true; } __result = customShopItem.LevelPrice(level); return false; } } [HarmonyPatch(typeof(ShopItemData), "GetRefundPrice")] internal static class ShopItemData_GetRefundPrice { private static bool Prefix(ShopItemData __instance, ref int __result) { CustomShopItem customShopItem = CustomShopItem.For(__instance); if (customShopItem == null) { return true; } __result = customShopItem.RefundAmount(); return false; } } [HarmonyPatch(typeof(ProgressionSaveFile), "PurchaseShopItem")] internal static class Progression_PurchaseShopItem { private static bool Prefix(ProgressionSaveFile __instance, ShopItemData shopItemData, ref bool __result) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown CustomShopItem customShopItem = CustomShopItem.For(shopItemData); if (customShopItem == null) { return true; } int currentLevel = customShopItem.CurrentLevel; int num = customShopItem.LevelPrice(currentLevel); __result = currentLevel < customShopItem.MaxLevel && __instance.silver >= num; if (__result) { if (num > 0) { __instance.RemoveSilver(num); } customShopItem.Level.Value = currentLevel + 1; SaveManager.Instance.SaveProgression(); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(27, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Bought "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(customShopItem.Title); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" level "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(currentLevel + 1); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" silver."); } log.LogInfo(val); } return false; } } [HarmonyPatch(typeof(ProgressionSaveFile), "RefundShopItem")] internal static class Progression_RefundShopItem { private static bool Prefix(ProgressionSaveFile __instance, ShopItemData shopItemData, ref bool __result) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown CustomShopItem customShopItem = CustomShopItem.For(shopItemData); if (customShopItem == null) { return true; } int currentLevel = customShopItem.CurrentLevel; __result = currentLevel > 0; if (__result) { int num = customShopItem.RefundAmount(); if (num > 0) { __instance.AddSilver(num); } customShopItem.Level.Value = currentLevel - 1; SaveManager.Instance.SaveProgression(); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(29, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Refunded "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(customShopItem.Title); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" level "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(currentLevel); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" for "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" silver."); } log.LogInfo(val); } return false; } } internal static class ShopSilverGuard { internal struct Before { internal bool Valid; internal int Silver; internal int Level; internal int Amount; } internal static Before Capture(ShopWindow window, bool refund) { ShopContainer currentContainer = window.currentContainer; ShopItemData val = ((currentContainer != null) ? currentContainer.data : null); SaveManager instance = SaveManager.Instance; ProgressionSaveFile val2 = ((instance != null) ? instance.progression : null); if ((Object)(object)val == (Object)null || val2 == null) { return default(Before); } return new Before { Valid = true, Silver = val2.silver, Level = val.GetLevel(), Amount = (refund ? val.GetRefundPrice() : ((UnlockableBase)val).GetPrice()) }; } internal static void Settle(ShopWindow window, Before before, bool refund) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Expected O, but got Unknown ShopContainer currentContainer = window.currentContainer; ShopItemData val = ((currentContainer != null) ? currentContainer.data : null); SaveManager instance = SaveManager.Instance; ProgressionSaveFile val2 = ((instance != null) ? instance.progression : null); if (!before.Valid || (Object)(object)val == (Object)null || val2 == null) { return; } int level = val.GetLevel(); int silver = val2.silver; string text = (refund ? "Refund" : "Buy"); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(38, 8, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<EShopItem>(val.eShopItem); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": level "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(before.Level); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(level); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(", silver "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(before.Silver); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(silver); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" (expected "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(refund ? "+" : "-"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(before.Amount); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(")"); } log.LogInfo(val3); CustomShopItem customShopItem = CustomShopItem.For(val); if (customShopItem == null || level == before.Level) { return; } int num = (refund ? (before.Silver + before.Amount) : (before.Silver - before.Amount)); if (silver != num) { if (silver > num) { val2.RemoveSilver(silver - num); } else { val2.AddSilver(num - silver); } SaveManager.Instance.SaveProgression(); ManualLogSource log2 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(25, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(customShopItem.Title); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": corrected silver "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(silver); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("."); } log2.LogWarning(val4); } } } [HarmonyPatch(typeof(ShopWindow), "Refund")] internal static class ShopWindow_Refund { private static void Prefix(ShopWindow __instance, out ShopSilverGuard.Before __state) { __state = ShopSilverGuard.Capture(__instance, refund: true); } private static void Postfix(ShopWindow __instance, ShopSilverGuard.Before __state) { ShopSilverGuard.Settle(__instance, __state, refund: true); } } [HarmonyPatch(typeof(ShopWindow), "Buy")] internal static class ShopWindow_Buy { private static void Prefix(ShopWindow __instance, out ShopSilverGuard.Before __state) { __state = ShopSilverGuard.Capture(__instance, refund: false); } private static void Postfix(ShopWindow __instance, ShopSilverGuard.Before __state) { ShopSilverGuard.Settle(__instance, __state, refund: false); } } [HarmonyPatch(typeof(ShopFooter), "Set")] internal static class ShopFooter_Set { private static void Postfix(ShopFooter __instance, ShopContainer shopContainerClicked) { CustomShopItem customShopItem = (((Object)(object)shopContainerClicked == (Object)null) ? null : CustomShopItem.For(shopContainerClicked.data)); if (customShopItem != null) { ((TMP_Text)__instance.t_title).text = customShopItem.Title; ((TMP_Text)__instance.t_description).text = customShopItem.FullDescription(); } } } [HarmonyPatch(typeof(MainMenu), "Start")] internal static class MainMenu_Start_RefundOverCap { private static void Postfix() { try { CustomShopItem.RefundLevelsOverCap(); } catch (Exception ex) { Plugin.Log.LogError((object)("Refunding levels over the cap failed: " + ex)); } } } internal static class FasterShrines { internal static CustomShopItem Shop; private static bool loggedThisMap; private const float InstantSeconds = 0.001f; private static readonly Dictionary<IntPtr, float> originalTime = new Dictionary<IntPtr, float>(); internal static void Bind(ConfigFile config, ConfigFile progress) { ConfigEntry<string> prices = config.Bind<string>("FasterShrines", "Prices", "200,200,200,200,200,200,200,200,200,200", "Silver price of each Faster Shrines level, comma separated. The count sets the max level (the last level is instant)."); Shop = new CustomShopItem(105, "Faster Shrines", progress.Bind<int>("Progress", "FasterShrinesLevel", 0, "Levels of the Faster Shrines shop upgrade bought. Managed by the mod."), () => CustomShopItem.ParsePrices(prices.Value), Description, null); } internal static float TimeFraction(int level) { return Math.Clamp(1f - (float)level / (float)Math.Max(1, Shop.MaxLevel), 0f, 1f); } private static string Describe(int level) { float num = TimeFraction(level); if (!(num <= 0f)) { return $"{num:P0} of the normal time"; } return "instant"; } private static string Description() { return $"Charge shrines fill faster. Each level cuts the charge time by {100f / (float)Shop.MaxLevel:0}% of normal; the last level fills them instantly."; } internal static void BeforeUpdate(ChargeShrine shrine) { int currentLevel = Shop.CurrentLevel; IntPtr pointer = ((Il2CppObjectBase)shrine).Pointer; if (!originalTime.TryGetValue(pointer, out var value)) { if (currentLevel <= 0) { return; } value = (originalTime[pointer] = shrine.chargeTime); } float num = TimeFraction(currentLevel); float num2 = ((currentLevel <= 0) ? value : Math.Max(0.001f, value * num)); if (shrine.chargeTime != num2) { shrine.chargeTime = num2; if (!loggedThisMap && currentLevel > 0) { loggedThisMap = true; Plugin.Log.LogInfo((object)($"Faster Shrines level {currentLevel}: shrine charge time {value:0.##}s -> " + ((num <= 0f) ? "instant." : $"{num2:0.##}s."))); } } } internal static void NewMap() { loggedThisMap = false; originalTime.Clear(); } } [HarmonyPatch(typeof(ChargeShrine), "Update")] internal static class ChargeShrine_Update { private static void Prefix(ChargeShrine __instance) { try { FasterShrines.BeforeUpdate(__instance); } catch (Exception ex) { Plugin.Log.LogError((object)("Faster Shrines failed: " + ex)); } } } [HarmonyPatch(typeof(MyTime), "OnNewStageStarted")] internal static class MyTime_OnNewStageStarted_FasterShrines { private static void Postfix() { FasterShrines.NewMap(); } } internal static class FoldCheck { internal unsafe static void Run() { //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Expected O, but got Unknown //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Expected O, but got Unknown //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Expected O, but got Unknown List<MethodBase> list = Harmony.GetAllPatchedMethods().ToList(); Dictionary<IntPtr, MethodBase> dictionary = new Dictionary<IntPtr, MethodBase>(); foreach (MethodBase item in list) { IntPtr intPtr = NativeAddress(item); if (intPtr != IntPtr.Zero) { dictionary[intPtr] = item; } } Dictionary<IntPtr, List<string>> dictionary2 = new Dictionary<IntPtr, List<string>>(); int num = 0; uint num2 = 0u; IntPtr* ptr = IL2CPP.il2cpp_domain_get_assemblies(IL2CPP.il2cpp_domain_get(), ref num2); for (uint num3 = 0u; num3 < num2; num3++) { IntPtr intPtr2 = IL2CPP.il2cpp_assembly_get_image(ptr[num3]); uint num4 = IL2CPP.il2cpp_image_get_class_count(intPtr2); for (uint num5 = 0u; num5 < num4; num5++) { IntPtr intPtr3 = IL2CPP.il2cpp_image_get_class(intPtr2, num5); IntPtr zero = IntPtr.Zero; IntPtr intPtr4; while ((intPtr4 = IL2CPP.il2cpp_class_get_methods(intPtr3, ref zero)) != IntPtr.Zero) { num++; IntPtr intPtr5 = *(IntPtr*)(void*)intPtr4; if (!(intPtr5 == IntPtr.Zero) && dictionary.ContainsKey(intPtr5)) { if (!dictionary2.TryGetValue(intPtr5, out var value)) { value = (dictionary2[intPtr5] = new List<string>()); } string text = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_class_get_namespace(intPtr3)); string text2 = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_class_get_name(intPtr3)); string text3 = Marshal.PtrToStringAnsi(IL2CPP.il2cpp_method_get_name(intPtr4)); value.Add((string.IsNullOrEmpty(text) ? "" : (text + ".")) + text2 + "." + text3); } } } } ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(52, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Fold check: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(dictionary.Count); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" patched methods, "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" game methods scanned."); } log.LogInfo(val); foreach (KeyValuePair<IntPtr, List<string>> item2 in dictionary2) { item2.Deconstruct(out var key, out var value2); IntPtr key2 = key; List<string> list3 = value2; MethodBase methodBase = dictionary[key2]; if (list3.Count <= 1) { continue; } ManualLogSource log2 = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(59, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Fold check: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(methodBase.DeclaringType?.Name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(methodBase.Name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" shares its native code with "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list3.Count - 1); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" other method(s):"); } log2.LogWarning(val2); foreach (string item3 in list3.Take(15)) { ManualLogSource log3 = Plugin.Log; val2 = new BepInExWarningLogInterpolatedStringHandler(4, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item3); } log3.LogWarning(val2); } if (list3.Count > 15) { ManualLogSource log4 = Plugin.Log; val2 = new BepInExWarningLogInterpolatedStringHandler(17, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ... and "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(list3.Count - 15); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" more"); } log4.LogWarning(val2); } } } private static IntPtr NativeAddress(MethodBase method) { try { FieldInfo il2CppMethodInfoPointerFieldForGeneratedMethod = Il2CppInteropUtils.GetIl2CppMethodInfoPointerFieldForGeneratedMethod(method); return (il2CppMethodInfoPointerFieldForGeneratedMethod == null) ? IntPtr.Zero : Read(il2CppMethodInfoPointerFieldForGeneratedMethod); } catch { return IntPtr.Zero; } } private unsafe static IntPtr Read(FieldInfo methodInfoField) { IntPtr intPtr = (IntPtr)methodInfoField.GetValue(null); if (!(intPtr == IntPtr.Zero)) { return *(IntPtr*)(void*)intPtr; } return IntPtr.Zero; } } [HarmonyPatch(typeof(DataManager), "Load")] internal static class DataManager_Load_FoldCheck { private static bool done; private static void Postfix() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (!done) { done = true; Stopwatch stopwatch = Stopwatch.StartNew(); try { FoldCheck.Run(); } catch (Exception ex) { Plugin.Log.LogError((object)("Fold check failed: " + ex)); } ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Fold check took "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<long>(stopwatch.ElapsedMilliseconds); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ms."); } log.LogInfo(val); } } } internal static class LevelupChoices { internal static CustomShopItem Shop; internal static bool ShufflingLevelup; private static RectTransform viewport; private static RectTransform content; private static ScrollRect scrollRect; private static bool loggedLayout; internal static int Extra => Shop.CurrentLevel; internal static void Bind(ConfigFile config, ConfigFile progress) { ConfigEntry<string> prices = config.Bind<string>("LevelUp", "MoreChoicesPrices", "200,200,200,200", "Silver price of each More Choices level, comma separated. The count sets the max level."); Shop = new CustomShopItem(103, "More Choices", progress.Bind<int>("Progress", "MoreChoicesLevel", 0, "Levels of the More Choices shop upgrade bought. Managed by the mod."), () => CustomShopItem.ParsePrices(prices.Value), Description, null); } private static string Description() { return "Each level adds one more option to choose from when you level up. The list scrolls."; } internal static void Prepare(UpgradePicker picker) { Il2CppReferenceArray<UpgradeButton> buttons = picker.buttons; if (buttons != null && ((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length != 0) { LogLayout(picker); EnsureScrollView(((Il2CppArrayBase<UpgradeButton>)(object)buttons)[0]); } } private static void AddExtraOptions(UpgradePicker picker) { //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown Il2CppReferenceArray<UpgradeButton> buttons = picker.buttons; int num = 0; HashSet<IntPtr> hashSet = new HashSet<IntPtr>(); foreach (UpgradeButton item in (Il2CppArrayBase<UpgradeButton>)(object)buttons) { if ((Object)(object)item != (Object)null && ((Component)item).gameObject.activeSelf) { num++; if (item.upgradable != null) { hashSet.Add(((Il2CppObjectBase)item.upgradable).Pointer); } } } int needed = num + Extra; EnsureButtonPool(picker, needed); buttons = picker.buttons; int num2 = 0; for (int i = 0; i < 10; i++) { if (num2 >= Extra) { break; } List<IUpgradable> randomUpgrades = InventoryUtility.GetRandomUpgrades(); if (randomUpgrades == null || randomUpgrades.Count == 0) { break; } Enumerator<IUpgradable> enumerator2 = randomUpgrades.GetEnumerator(); while (enumerator2.MoveNext()) { IUpgradable current2 = enumerator2.Current; if (num2 >= Extra) { break; } if (current2 != null && hashSet.Add(((Il2CppObjectBase)current2).Pointer)) { UpgradeButton obj = ((Il2CppArrayBase<UpgradeButton>)(object)buttons)[num + num2]; ((Component)obj).gameObject.SetActive(true); obj.SetUpgrade(current2); num2++; } } } for (int j = num + num2; j < ((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length; j++) { ((Component)((Il2CppArrayBase<UpgradeButton>)(object)buttons)[j]).gameObject.SetActive(false); } ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(45, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("More Choices: game showed "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", added "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" of "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Extra); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" extra."); } log.LogInfo(val); } private static void EnsureButtonPool(UpgradePicker picker, int needed) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown Il2CppReferenceArray<UpgradeButton> buttons = picker.buttons; if (((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length < needed) { UpgradeButton[] array = (UpgradeButton[])(object)new UpgradeButton[needed]; for (int i = 0; i < ((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length; i++) { array[i] = ((Il2CppArrayBase<UpgradeButton>)(object)buttons)[i]; } UpgradeButton val = ((Il2CppArrayBase<UpgradeButton>)(object)buttons)[((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length - 1]; for (int j = ((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length; j < needed; j++) { UpgradeButton component = UiClone.Clone(((Component)val).gameObject, ((Component)val).transform.parent, $"Mod_UpgradeButton{j}", stripLocalization: false).GetComponent<UpgradeButton>(); component.upgradePicker = picker; array[j] = component; } picker.buttons = new Il2CppReferenceArray<UpgradeButton>(array); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(36, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("More Choices: level-up buttons "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(((Il2CppArrayBase<UpgradeButton>)(object)buttons).Length); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(needed); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("."); } log.LogInfo(val2); } } private static void EnsureScrollView(UpgradeButton first) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Component)first).transform.parent; RectTransform val = ((parent != null) ? ((Component)parent).gameObject.GetComponent<RectTransform>() : null); if ((Object)(object)val == (Object)null || ((Object)(object)content != (Object)null && ((Il2CppObjectBase)content).Pointer == ((Il2CppObjectBase)val).Pointer)) { return; } Transform parent2 = ((Transform)val).parent; if (!((Object)(object)parent2 == (Object)null)) { GameObject val2 = new GameObject("Mod_ChoicesViewport"); RectTransform val3 = val2.AddComponent<RectTransform>(); ((Transform)val3).SetParent(parent2, false); ((Transform)val3).SetSiblingIndex(((Transform)val).GetSiblingIndex()); val3.anchorMin = val.anchorMin; val3.anchorMax = val.anchorMax; val3.pivot = val.pivot; val3.anchoredPosition = val.anchoredPosition; val3.sizeDelta = val.sizeDelta; ((Transform)val3).localScale = ((Transform)val).localScale; Rect rect = val.rect; Vector2 size = ((Rect)(ref rect)).size; LayoutElement val4 = val2.AddComponent<LayoutElement>(); LayoutElement component = ((Component)val).gameObject.GetComponent<LayoutElement>(); if ((Object)(object)component != (Object)null) { val4.minWidth = component.minWidth; val4.minHeight = component.minHeight; val4.preferredWidth = component.preferredWidth; val4.preferredHeight = component.preferredHeight; val4.flexibleWidth = component.flexibleWidth; val4.flexibleHeight = component.flexibleHeight; val4.layoutPriority = component.layoutPriority; ((Behaviour)component).enabled = false; } else { val4.preferredWidth = size.x; val4.preferredHeight = size.y; } val2.AddComponent<RectMask2D>(); Image obj = val2.AddComponent<Image>(); ((Graphic)obj).color = new Color(0f, 0f, 0f, 0f); ((Graphic)obj).raycastTarget = false; ((Transform)val).SetParent((Transform)(object)val3, false); val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(1f, 1f); val.pivot = new Vector2(0.5f, 1f); val.anchoredPosition = Vector2.zero; val.sizeDelta = new Vector2(0f, size.y); ((Transform)val).localScale = Vector3.one; (((Component)val).gameObject.GetComponent<ContentSizeFitter>() ?? ((Component)val).gameObject.AddComponent<ContentSizeFitter>()).verticalFit = (FitMode)2; ScrollRect obj2 = val2.AddComponent<ScrollRect>(); obj2.content = val; obj2.viewport = val3; obj2.horizontal = false; obj2.vertical = true; obj2.movementType = (MovementType)2; obj2.scrollSensitivity = 40f; viewport = val3; scrollRect = obj2; content = val; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(44, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("More Choices: wrapped '"); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(((Object)val).name); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("' in a scroll view "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<float>(size.x, "F0"); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("x"); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<float>(size.y, "F0"); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("."); } log.LogInfo(val5); } } internal static void AfterShuffle(UpgradePicker picker) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) AddExtraOptions(picker); if (!((Object)(object)content == (Object)null)) { LayoutRebuilder.ForceRebuildLayoutImmediate(content); ScrollRect obj = scrollRect; if (obj != null) { obj.StopMovement(); } content.anchoredPosition = Vector2.zero; LinkNavigation(picker); } } private static void LinkNavigation(UpgradePicker picker) { //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Invalid comparison between Unknown and I4 List<Button> list = new List<Button>(); foreach (UpgradeButton item in (Il2CppArrayBase<UpgradeButton>)(object)picker.buttons) { Button val = ((item != null) ? ((Component)item).gameObject.GetComponent<Button>() : null); if ((Object)(object)val != (Object)null && ((Component)item).gameObject.activeSelf) { list.Add(val); } } if (list.Count == 0) { return; } List<Button> list2 = FooterButtons(picker.levelupScreen); Button val2 = ((list2.Count > 0) ? list2[0] : null); for (int i = 0; i < list.Count; i++) { Navigation navigation = ((Selectable)list[i]).navigation; navigation.mode = (Mode)4; navigation.selectOnUp = (Selectable)((i > 0) ? ((object)list[i - 1]) : ((object)navigation.selectOnUp)); navigation.selectOnDown = (Selectable)((i < list.Count - 1) ? list[i + 1] : (((object)val2) ?? ((object)navigation.selectOnDown))); ((Selectable)list[i]).navigation = navigation; } Button selectOnUp = list[list.Count - 1]; foreach (Button item2 in list2) { Navigation navigation2 = ((Selectable)item2).navigation; if ((int)navigation2.mode == 4) { navigation2.selectOnUp = (Selectable)(object)selectOnUp; ((Selectable)item2).navigation = navigation2; } } } private static List<Button> FooterButtons(LevelupScreen screen) { List<Button> list = new List<Button>(); if ((Object)(object)screen == (Object)null) { return list; } GameObject[] array = new GameObject[4]; MyButtonOffersUtility b_banish = screen.b_banish; array[0] = ((b_banish != null) ? ((Component)b_banish).gameObject : null); MyButtonOffersUtility b_skip = screen.b_skip; array[1] = ((b_skip != null) ? ((Component)b_skip).gameObject : null); MyButtonOffersUtility b_refresh = screen.b_refresh; array[2] = ((b_refresh != null) ? ((Component)b_refresh).gameObject : null); MyButtonNormal b_leave = screen.b_leave; array[3] = ((b_leave != null) ? ((Component)b_leave).gameObject : null); GameObject[] array2 = (GameObject[])(object)array; foreach (GameObject val in array2) { Button val2 = (((Object)(object)val == (Object)null) ? null : val.GetComponent<Button>()); if ((Object)(object)val2 != (Object)null && val.activeInHierarchy && ((Selectable)val2).interactable) { list.Add(val2); } } list.Sort((Button a, Button b) => ((Component)a).transform.position.x.CompareTo(((Component)b).transform.position.x)); return list; } internal static void FollowSelection() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)content == (Object)null || (Object)(object)viewport == (Object)null || (Object)(object)EventSystem.current == (Object)null) { return; } GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject; if ((Object)(object)currentSelectedGameObject == (Object)null || !currentSelectedGameObject.transform.IsChildOf((Transform)(object)content)) { return; } RectTransform component = currentSelectedGameObject.GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null)) { Il2CppStructArray<Vector3> val = new Il2CppStructArray<Vector3>(4L); component.GetWorldCorners(val); float y = ((Il2CppArrayBase<Vector3>)(object)val)[1].y; float y2 = ((Il2CppArrayBase<Vector3>)(object)val)[0].y; viewport.GetWorldCorners(val); float y3 = ((Il2CppArrayBase<Vector3>)(object)val)[1].y; float y4 = ((Il2CppArrayBase<Vector3>)(object)val)[0].y; float num = 0f; if (y > y3) { num = y - y3; } else if (y2 < y4) { num = y2 - y4; } if (num != 0f) { RectTransform obj = content; ((Transform)obj).position = ((Transform)obj).position - new Vector3(0f, num, 0f); } } } private static void LogLayout(UpgradePicker picker) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) if (loggedLayout) { return; } loggedLayout = true; UpgradeButton val = ((Il2CppArrayBase<UpgradeButton>)(object)picker.buttons)[0]; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(63, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("More Choices: picker has "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(((Il2CppArrayBase<UpgradeButton>)(object)picker.buttons).Length); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" buttons, numUpgrades="); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(picker.numUpgrades); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", parent '"); BepInExInfoLogInterpolatedStringHandler obj = val2; Transform parent = ((Component)val).transform.parent; ((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((parent != null) ? ((Object)parent).name : null); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("' > '"); BepInExInfoLogInterpolatedStringHandler obj2 = val2; Transform parent2 = ((Component)val).transform.parent; object obj3; if (parent2 == null) { obj3 = null; } else { Transform parent3 = parent2.parent; obj3 = ((parent3 != null) ? ((Object)parent3).name : null); } ((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((string)obj3); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'"); } log.LogInfo(val2); Transform parent4 = ((Component)val).transform.parent; while ((Object)(object)parent4 != (Object)null) { string text = string.Join(",", ((IEnumerable<Component>)((Component)parent4).gameObject.GetComponents<Component>()).Select((Component c) => ((MemberInfo)((Object)c).GetIl2CppType()).Name)); RectTransform component = ((Component)parent4).gameObject.GetComponent<RectTransform>(); ManualLogSource log2 = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(12, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)parent4).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": size="); BepInExInfoLogInterpolatedStringHandler obj4 = val2; Vector2? obj5; if (component == null) { obj5 = null; } else { Rect rect = component.rect; obj5 = ((Rect)(ref rect)).size; } ((BepInExLogInterpolatedStringHandler)obj4).AppendFormatted<Vector2?>(obj5); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ["); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]"); } log2.LogInfo(val2); if (!((Object)(object)((Component)parent4).gameObject.GetComponent<Canvas>() != (Object)null)) { parent4 = parent4.parent; continue; } break; } } } [HarmonyPatch(typeof(UpgradePicker), "ShuffleUpgrades")] internal static class UpgradePicker_ShuffleUpgrades { private static readonly Stopwatch timer = new Stopwatch(); private static double prepareMs; private static void Prefix(UpgradePicker __instance, EEncounter encounterType) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) timer.Restart(); prepareMs = 0.0; LevelupChoices.ShufflingLevelup = (int)encounterType == 0 && LevelupChoices.Extra > 0; if (LevelupChoices.ShufflingLevelup) { try { LevelupChoices.Prepare(__instance); } catch (Exception ex) { Plugin.Log.LogError((object)("More Choices: prepare failed: " + ex)); } prepareMs = timer.Elapsed.TotalMilliseconds; timer.Restart(); } } private static void Postfix(UpgradePicker __instance, EEncounter encounterType) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) double totalMilliseconds = timer.Elapsed.TotalMilliseconds; timer.Restart(); if (LevelupChoices.ShufflingLevelup) { LevelupChoices.ShufflingLevelup = false; try { LevelupChoices.AfterShuffle(__instance); } catch (Exception ex) { Plugin.Log.LogError((object)("More Choices: after shuffle failed: " + ex)); } } Performance.Mark($"shuffle {encounterType} (game {totalMilliseconds:F1}ms, mod {prepareMs + timer.Elapsed.TotalMilliseconds:F1}ms)"); } } [HarmonyPatch(typeof(UpgradePicker), "Update")] internal static class UpgradePicker_Update { private static void Postfix() { LevelupChoices.FollowSelection(); } } [HarmonyPatch(typeof(LevelupScreen), "ShowLevelupScreen")] internal static class LevelupScreen_ShowLevelupScreen_Timing { private static readonly Stopwatch timer = new Stopwatch(); private static void Prefix() { timer.Restart(); } private static void Postfix() { Performance.Mark($"opened level-up ({timer.Elapsed.TotalMilliseconds:F1}ms)"); } } internal static class LinearKeys { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<float> ChancePerKey; internal static void Bind(ConfigFile config) { Enabled = config.Bind<bool>("Keys", "LinearKeys", true, "Each key adds a flat chance to open a chest for free."); ChancePerKey = config.Bind<float>("Keys", "ChancePerKey", 0.1f, "Free-chest chance per key (0.1 = 10%, so 10 keys = 100%)."); } } [HarmonyPatch(typeof(ItemKey), "OnInitOrAmountChanged")] internal static class ItemKey_OnInitOrAmountChanged { private static void Postfix(ItemKey __instance) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown if (LinearKeys.Enabled.Value && __instance != null) { float currentChance = __instance.currentChance; __instance.currentChance = Math.Clamp((float)((ItemBase)__instance).amount * LinearKeys.ChancePerKey.Value, 0f, 1f); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(51, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Keys: "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(((ItemBase)__instance).amount); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" -> free chest chance "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(__instance.currentChance, "P0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (vanilla "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(currentChance, "P1"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", GetChance "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(__instance.GetChance(), "P1"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")"); } log.LogInfo(val); } } } internal static class ManualFire { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<KeyCode> MouseButton; internal static ConfigEntry<KeyCode> PadButton; internal static ConfigEntry<string> PadButtonNames; internal static ConfigEntry<bool> FireButtonDoesNotJump; internal static ConfigEntry<bool> LogButtons; internal static ConfigEntry<string> JumpButtonNames; internal static ConfigEntry<string> KeyboardJumpKeys; internal static ConfigEntry<string> JumpAxisNames; internal static ConfigEntry<bool> LogAxes; internal static ConfigEntry<float> BaseInterval; internal static ConfigEntry<float> BaseStamina; internal static ConfigEntry<float> StaminaPerLevel; internal static ConfigEntry<float> RegenPerSecond; internal static ConfigEntry<float> BaseCost; internal static ConfigEntry<float> CostReductionPerLevel; internal static ConfigEntry<float> MinCost; internal static ConfigEntry<float> LateCostReduction; internal static ConfigEntry<string> AlwaysOnWeapons; internal static ConfigEntry<float> AlwaysOnDamage; internal static ConfigEntry<string> UnaffectedWeapons; internal static CustomShopItem AutoFire; internal static CustomShopItem StaminaUp; internal static CustomShopItem Efficiency; internal static CustomShopItem FireRate; internal static CustomShopItem Recharge; internal static ConfigEntry<float> RegenPerLevel; internal static float Stamina; internal static bool InRun; private static float nextActionAt; private static bool wasHeld; private static float lastLog; private static float lastHitLog; private static int loggedHits = -1; internal static bool Releasing; internal static readonly HashSet<string> PassiveWeapons = new HashSet<string>(StringComparer.OrdinalIgnoreCase); internal static readonly Dictionary<IntPtr, float> FullDamageUntil = new Dictionary<IntPtr, float>(); internal static int ReducedHits; internal static int FullHits; internal static float MaxStamina => MaxStaminaAt(StaminaUp?.CurrentLevel ?? 0); internal static float CostPerWeapon => CostAt(Efficiency?.CurrentLevel ?? 0); internal static float Regen => RegenAt(Recharge?.CurrentLevel ?? 0); internal static float Interval => BaseInterval.Value / (float)(1 + (FireRate?.CurrentLevel ?? 0)); internal static bool Active => Enabled.Value; internal static void Bind(ConfigFile config, ConfigFile progress) { Enabled = config.Bind<bool>("ManualFire", "Enabled", true, "Weapons only fire when you press the fire button (false = the game's normal auto attacks)."); MouseButton = config.Bind<KeyCode>("ManualFire", "MouseButton", (KeyCode)323, "Fire button on mouse / keyboard."); PadButton = config.Bind<KeyCode>("ManualFire", "PadButton", (KeyCode)335, "Fire button on a controller through Unity input (JoystickButton5 = R1 / RB); usually not seen, the game reads controllers through Rewired."); PadButtonNames = config.Bind<string>("ManualFire", "PadButtonNames", "Button 5,Right Shoulder,Right Shoulder 1,RB,R1,Right Bumper", "Controller fire button, by the game controller system's (Rewired) button name. The log lists your controller's button names once."); LogButtons = config.Bind<bool>("ManualFire", "LogControllerButtons", false, "Log each controller button name as it's pressed (to find a button's name)."); FireButtonDoesNotJump = config.Bind<bool>("ManualFire", "OnlyJumpButtonsJump", true, "On a controller, only the buttons in OtherJumpButtonNames (A) jump; R1 and any other button bound to jump don't. The keyboard keys in KeyboardJumpKeys still jump."); JumpButtonNames = config.Bind<string>("ManualFire", "OtherJumpButtonNames", "Button 0", "The controller buttons that jump (Button 0 = A)."); KeyboardJumpKeys = config.Bind<string>("ManualFire", "KeyboardJumpKeys", "Space", "Keyboard keys that still jump (Unity KeyCode names, comma separated)."); JumpAxisNames = config.Bind<string>("ManualFire", "JumpTriggerNames", "", "Controller trigger(s) that also jump, by the controller system's axis name (Axis 4 = L2, which the game uses to aim). Empty = off."); LogAxes = config.Bind<bool>("ManualFire", "LogControllerTriggers", false, "Log each controller axis/trigger as it's pulled past halfway (to find a trigger's name)."); BaseInterval = config.Bind<float>("ManualFire", "SecondsPerAction", 0.5f, "Time between fire actions at Fire Rate level 0. Each Fire Rate level adds one more action in this time."); BaseStamina = config.Bind<float>("ManualFire", "BaseStamina", 5f, "Stamina points at Stamina level 0."); StaminaPerLevel = config.Bind<float>("ManualFire", "StaminaPerLevel", 2f, "Extra stamina points per Stamina upgrade level."); RegenPerSecond = config.Bind<float>("ManualFire", "RegenPerSecond", 1f, "Stamina refilled per second while not firing."); BaseCost = config.Bind<float>("ManualFire", "StaminaPerWeapon", 1f, "Stamina each weapon costs per action at Efficiency level 0."); CostReductionPerLevel = config.Bind<float>("ManualFire", "CostReductionPerLevel", 0.1f, "Stamina per weapon saved per Efficiency upgrade level."); LateCostReduction = config.Bind<float>("ManualFire", "CostReductionPerLevelAfter5", 0.05f, "Stamina per weapon saved by each Efficiency level above 5."); MinCost = config.Bind<float>("ManualFire", "MinStaminaPerWeapon", 0.25f, "Efficiency can't lower the cost per weapon below this."); AlwaysOnWeapons = config.Bind<string>("ManualFire", "AlwaysOnWeapons", "auto", "Passive weapons that keep working on their own (at reduced damage) instead of waiting for the fire button. \"auto\" = every weapon whose attack is a constant attack in the game data (the log lists them); or a comma-separated list of weapon names."); UnaffectedWeapons = config.Bind<string>("ManualFire", "UnaffectedWeapons", "Aegis,Chunkers", "Weapons left exactly as in the normal game: they fire on their own at full damage and cost no stamina."); AlwaysOnDamage = config.Bind<float>("ManualFire", "AlwaysOnDamage", 0.1f, "Damage multiplier for passive weapons while not triggered (0.1 = 10%); triggering releases full damage."); ConfigEntry<string> autoPrice = config.Bind<string>("ManualFire", "AutoFirePrice", "200", "Silver price of Auto Fire (hold to keep firing)."); ConfigEntry<string> staminaPrices = config.Bind<string>("ManualFire", "StaminaPrices", "50,50,50,50,100,100,100,100,150,150", "Silver price of each Stamina level."); ConfigEntry<string> efficiencyPrices = config.Bind<string>("ManualFire", "EfficiencyPrices", "50,50,50,50,100,100,100,100,150,150", "Silver price of each Efficiency level."); ConfigEntry<string> ratePrices = config.Bind<string>("ManualFire", "FireRatePrices", "50,50,50,50,100,100", "Silver price of each Fire Rate level."); ConfigEntry<string> rechargePrices = config.Bind<string>("ManualFire", "RechargePrices", "50,50,50,50,100,100,100,100,150,150", "Silver price of each Recharge level."); RegenPerLevel = config.Bind<float>("ManualFire", "RegenPerLevel", 0.5f, "Extra stamina refilled per second per Recharge upgrade level."); AutoFire = new CustomShopItem(107, "Auto Fire", progress.Bind<int>("Progress", "AutoFireLevel", 0, "1 when Auto Fire is owned. Managed by the mod."), () => CustomShopItem.ParsePrices(autoPrice.Value), () => "Hold the fire button to keep firing, machine-gun style, while stamina lasts.", null); StaminaUp = new CustomShopItem(108, "Stamina", progress.Bind<int>("Progress", "StaminaLevel", 0, "Stamina upgrade levels. Managed by the mod."), () => CustomShopItem.ParsePrices(staminaPrices.Value), () => $"More stamina for firing. Each level adds {StaminaPerLevel.Value:0.#} stamina.", null); Efficiency = new CustomShopItem(109, "Efficiency", progress.Bind<int>("Progress", "EfficiencyLevel", 0, "Efficiency upgrade levels. Managed by the mod."), () => CustomShopItem.ParsePrices(efficiencyPrices.Value), () => $"Each weapon costs less stamina to fire. Levels 1-5 save {CostReductionPerLevel.Value:0.##} stamina per weapon each, later levels {LateCostReduction.Value:0.##}.", null
MoreSlots.dll
Decompiled 10 hours agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using Assets.Scripts.Inventory__Items__Pickups; using Assets.Scripts.Saves___Serialization.SaveFiles; using Assets.Scripts._Data.ShopItems; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("MoreSlots")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.3.0.0")] [assembly: AssemblyInformationalVersion("0.3.0+9583c9456c88608702ad5b96818742c7ac815822")] [assembly: AssemblyProduct("MoreSlots")] [assembly: AssemblyTitle("MoreSlots")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.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 MoreSlots { [BepInPlugin("com.megabonkmods.moreslots", "MoreSlots", "0.3.0")] public class Plugin : BasePlugin { public const string Guid = "com.megabonkmods.moreslots"; public const string Name = "MoreSlots"; public const string Version = "0.3.0"; internal static ManualLogSource Log; public override void Load() { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown Log = ((BasePlugin)this).Log; SlotShop.Tomes = new SlotShop((EShopItem)4, ((BasePlugin)this).Config.Bind<int>("Tomes", "ExtraSlots", 4, "Additional tome slot levels added to the shop's Tomes upgrade."), ((BasePlugin)this).Config.Bind<int>("Tomes", "PricePerSlot", 135, "Silver cost of each added tome slot level.")); SlotShop.Weapons = new SlotShop((EShopItem)3, ((BasePlugin)this).Config.Bind<int>("Weapons", "ExtraSlots", 4, "Additional weapon slot levels added to the shop's Weapons upgrade."), ((BasePlugin)this).Config.Bind<int>("Weapons", "PricePerSlot", 125, "Silver cost of each added weapon slot level.")); Harmony val = new Harmony("com.megabonkmods.moreslots"); val.PatchAll(); MaxSlotPatches.Apply(val); ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(13, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("MoreSlots"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("0.3.0"); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" loaded. "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<SlotShop>(SlotShop.Tomes); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" | "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<SlotShop>(SlotShop.Weapons); } log.LogInfo(val2); } } internal class SlotShop { internal static SlotShop Tomes; internal static SlotShop Weapons; internal readonly EShopItem Item; internal readonly ConfigEntry<int> Extra; internal readonly ConfigEntry<int> Price; internal int OrigMax = -1; internal bool Ready => OrigMax >= 0; internal SlotShop(EShopItem item, ConfigEntry<int> extra, ConfigEntry<int> price) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Item = item; Extra = extra; Price = price; } internal static SlotShop For(EShopItem item) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)item != 4) { if ((int)item != 3) { return null; } return Weapons; } return Tomes; } internal static SlotShop For(ShopItemData data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) SlotShop slotShop = For(data.eShopItem); if (slotShop == null || !slotShop.Ready) { return null; } return slotShop; } internal int CurrentLevel() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) SaveManager instance = SaveManager.Instance; object obj; if (instance == null) { obj = null; } else { ProgressionSaveFile progression = instance.progression; obj = ((progression != null) ? progression.shopItems : null); } Dictionary<EShopItem, int> val = (Dictionary<EShopItem, int>)obj; int result = default(int); if (val == null || !val.TryGetValue(Item, ref result)) { return 0; } return result; } internal int BoughtExtra() { if (!Ready) { return 0; } return Math.Max(0, CurrentLevel() - OrigMax); } public override string ToString() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) return $"{Item}: +{Extra.Value} @ {Price.Value} silver"; } } [HarmonyPatch(typeof(DataManager), "Load")] internal static class DataManager_Load { private static void Postfix(DataManager __instance) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) SlotShop[] array = new SlotShop[2] { SlotShop.Tomes, SlotShop.Weapons }; bool flag = default(bool); foreach (SlotShop slotShop in array) { ShopItemData shopItemData = __instance.GetShopItemData(slotShop.Item); if ((Object)(object)shopItemData == (Object)null) { ManualLogSource log = Plugin.Log; BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(34, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<EShopItem>(slotShop.Item); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" shop item not found; not patched."); } log.LogWarning(val); continue; } if (slotShop.OrigMax < 0) { slotShop.OrigMax = shopItemData.maxLevel; } shopItemData.maxLevel = slotShop.OrigMax + slotShop.Extra.Value; ManualLogSource log2 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(25, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<EShopItem>(slotShop.Item); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" shop item: maxLevel "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(slotShop.OrigMax); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(shopItemData.maxLevel); } log2.LogInfo(val2); } } } [HarmonyPatch(typeof(ShopItemData), "GetMaxLevel")] internal static class ShopItemData_GetMaxLevel { private static void Postfix(ShopItemData __instance, ref int __result) { if (SlotShop.For(__instance) != null) { __result = __instance.maxLevel; } } } [HarmonyPatch(typeof(ShopItemData), "IsMaxLevel")] internal static class ShopItemData_IsMaxLevel { private static void Postfix(ShopItemData __instance, ref bool __result) { SlotShop slotShop = SlotShop.For(__instance); if (slotShop != null) { __result = slotShop.CurrentLevel() >= __instance.maxLevel; } } } [HarmonyPatch(typeof(ShopItemData), "GetLevelPrice")] internal static class ShopItemData_GetLevelPrice { private static bool Prefix(ShopItemData __instance, int level, ref int __result) { SlotShop slotShop = SlotShop.For(__instance); if (slotShop == null || level < slotShop.OrigMax) { return true; } __result = slotShop.Price.Value; return false; } } internal static class MaxSlotPatches { private enum Kind { None, Tomes, Weapons, Both } [ThreadStatic] private static int depth; [ThreadStatic] private static Kind kind; internal static void Apply(Harmony harmony) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(InventoryUtility), "GetNumMaxTomeSlots", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(InventoryUtility), "GetNumMaxWeaponSlots", (Type[])null, (Type[])null); bool flag = NativeAddress("NativeMethodInfoPtr_GetNumMaxTomeSlots_Public_Static_Int32_0") == NativeAddress("NativeMethodInfoPtr_GetNumMaxWeaponSlots_Public_Static_Int32_0"); harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(MaxSlotPatches), "CapPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); if (!flag) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(MaxSlotPatches), "CapPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Scope(harmony, "GetNumAvailableTomeSlots", "TomesPrefix"); Scope(harmony, "CanUnlockTomes", "TomesPrefix"); Scope(harmony, "GetNumAvailableWeaponSlots", "WeaponsPrefix"); Scope(harmony, "CanUnlockWeapons", "WeaponsPrefix"); ScopeOn(harmony, AccessTools.Method(typeof(InventoryHud), "Refresh", (Type[])null, (Type[])null), "BothPrefix"); ScopeOn(harmony, AccessTools.Method(typeof(UpgradeInventoryUI), "Refresh", (Type[])null, (Type[])null), "BothPrefix"); ManualLogSource log = Plugin.Log; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(65, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Slot caps patched ("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(flag ? "tome and weapon caps share one native function" : "separately"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("), applied only inside the game's slot checks."); } log.LogInfo(val); } private static void Scope(Harmony harmony, string method, string prefix) { ScopeOn(harmony, AccessTools.Method(typeof(InventoryUtility), method, (Type[])null, (Type[])null), prefix); } private static void ScopeOn(Harmony harmony, MethodBase method, string prefix) { //IL_000e: 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) //IL_0030: Expected O, but got Unknown //IL_0030: Expected O, but got Unknown harmony.Patch(method, new HarmonyMethod(typeof(MaxSlotPatches), prefix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(MaxSlotPatches), "ExitScope", (Type[])null), (HarmonyMethod)null); } private static void Enter(Kind k) { if (depth++ == 0 || k != Kind.Both) { kind = k; } } private static void TomesPrefix(out Kind __state) { __state = kind; Enter(Kind.Tomes); } private static void WeaponsPrefix(out Kind __state) { __state = kind; Enter(Kind.Weapons); } private static void BothPrefix(out Kind __state) { __state = kind; Enter(Kind.Both); } private static Exception ExitScope(Exception __exception, Kind __state) { if (depth > 0 && --depth > 0) { kind = __state; } else { kind = Kind.None; } return __exception; } private static void CapPostfix(ref int __result) { if (depth != 0) { int num = __result; __result = num + kind switch { Kind.Tomes => SlotShop.Tomes.BoughtExtra(), Kind.Weapons => SlotShop.Weapons.BoughtExtra(), _ => Math.Max(SlotShop.Tomes.BoughtExtra(), SlotShop.Weapons.BoughtExtra()), }; } } private unsafe static IntPtr NativeAddress(string methodInfoField) { return *(IntPtr*)(void*)(IntPtr)AccessTools.Field(typeof(InventoryUtility), methodInfoField).GetValue(null); } } }