Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of No Limits v0.2.1
plugins/NoLimits/NoLimits.dll
Decompiled 11 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using R2API; using R2API.Networking; using R2API.Networking.Interfaces; using R2API.Utils; using RoR2; using RoR2.Items; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace NoLimits; internal static class AffineItemRules { private sealed class Count { internal FieldInfo Item; internal List<CodeInstruction> Load; internal string Key; } private sealed class Expr { internal Count Count; internal double Slope; internal double Offset; internal int Start; internal bool Floating; internal bool Double; } private sealed class Rule { internal int Start; internal int End; internal Expr Expr; } [HarmonyPatch] private static class ItemMethods { private static IEnumerable<MethodBase> TargetMethods() { Assembly assembly = typeof(Run).Assembly; string[] behaviors = RuleTargets.Behaviors; foreach (string text in behaviors) { string[] array = text.Split('|'); Type type = assembly.GetType(array[0]); Type type2 = assembly.GetType(array[1]); if (type != null && type2 != null) { Behaviors[type] = AccessTools.Field(type2, array[2]); } } string[] cachedCounts = RuleTargets.CachedCounts; foreach (string text2 in cachedCounts) { string[] array2 = text2.Split('|'); Type type3 = assembly.GetType(array2[0]); Type type4 = assembly.GetType(array2[2]); if (type3 != null && type4 != null) { FieldInfo fieldInfo = AccessTools.Field(type3, array2[1]); FieldInfo fieldInfo2 = AccessTools.Field(type4, array2[3]); if (fieldInfo != null && fieldInfo2 != null) { Cached[fieldInfo] = fieldInfo2; } } } HashSet<MethodBase> seen = new HashSet<MethodBase>(); try { string[] methods = RuleTargets.Methods; foreach (string row in methods) { string[] parts = row.Split('|'); Type type5 = assembly.GetType(parts[0]); if (type5 == null || type5.ContainsGenericParameters) { continue; } try { MethodInfo[] methods2 = type5.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo method in methods2) { if (method.Name == parts[1] && !method.ContainsGenericParameters && method.GetMethodBody() != null && seen.Add(method)) { yield return method; } } } finally { } } } finally { } } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, MethodBase __originalMethod) { List<CodeInstruction> codes = input.ToList(); Dictionary<int, Count> locals = new Dictionary<int, Count>(); List<Rule> candidates = new List<Rule>(); for (int i = 0; i < codes.Count; i++) { int num = Local(codes[i], store: true); if (num >= 0) { int cursor = i - 1; Expr expr = Parse(codes, ref cursor, locals, __originalMethod.DeclaringType, 0); if (expr != null && expr.Count != null && expr.Slope == 1.0 && expr.Offset == 0.0) { locals[num] = new Count { Item = expr.Count.Item, Key = num + ":" + expr.Count.Item.ToString(), Load = new List<CodeInstruction> { new CodeInstruction(OpCodes.Ldloc, (object)(short)num) } }; } else { locals.Remove(num); } } MethodInfo methodInfo = codes[i].operand as MethodInfo; if (i > 0 && i + 1 < codes.Count && methodInfo != null && methodInfo.DeclaringType == typeof(Inventory) && methodInfo.Name.StartsWith("GetItemCount", StringComparison.Ordinal)) { FieldInfo fieldInfo = codes[i - 1].operand as FieldInfo; int num2 = Local(codes[i + 1], store: true); if (fieldInfo != null && fieldInfo.FieldType == typeof(ItemDef) && num2 >= 0) { locals[num2] = new Count { Item = fieldInfo, Key = num2 + ":" + fieldInfo.ToString(), Load = new List<CodeInstruction> { new CodeInstruction(OpCodes.Ldloc, (object)(short)num2) } }; } } if (codes[i].opcode != OpCodes.Add) { continue; } int cursor2 = i; Expr expr2 = Parse(codes, ref cursor2, locals, __originalMethod.DeclaringType, 0); if (expr2 != null && expr2.Count != null && !(expr2.Slope <= 0.0) && !(expr2.Offset <= 0.0) && !double.IsNaN(expr2.Offset) && !double.IsInfinity(expr2.Offset) && !NativeLinear.Contains(expr2.Count.Item.Name)) { if (expr2.Count.Item.Name == "ShieldOnly") { expr2.Offset = Math.Max(0.0, expr2.Offset - 1.0); } int j; for (j = i + 1; j < codes.Count && (codes[j].opcode == OpCodes.Conv_R4 || codes[j].opcode == OpCodes.Conv_R8); j++) { } if ((j >= codes.Count || !(codes[j].opcode == OpCodes.Div)) && (j + 1 >= codes.Count || !(codes[j + 1].operand is MethodInfo) || !(((MethodInfo)codes[j + 1].operand).Name == "Pow"))) { candidates.Add(new Rule { Start = expr2.Start, End = i, Expr = expr2 }); } } } List<Rule> rules = candidates.Where((Rule a) => !candidates.Any((Rule b) => b != a && b.Start <= a.Start && b.End > a.End && b.Expr.Count.Key == a.Expr.Count.Key)).ToList(); int i2; for (i2 = 0; i2 < codes.Count; i2++) { yield return codes[i2]; foreach (Rule rule in rules.Where((Rule r) => r.End == i2)) { foreach (CodeInstruction load in rule.Expr.Count.Load) { yield return Clone(load); } if (rule.Expr.Double) { yield return new CodeInstruction(OpCodes.Ldc_R8, (object)rule.Expr.Offset); } else if (rule.Expr.Floating) { yield return new CodeInstruction(OpCodes.Ldc_R4, (object)(float)rule.Expr.Offset); } else { yield return new CodeInstruction(OpCodes.Ldc_I4, (object)(int)rule.Expr.Offset); } yield return new CodeInstruction(OpCodes.Ldsfld, (object)rule.Expr.Count.Item); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(AffineItemRules), rule.Expr.Double ? "Double" : (rule.Expr.Floating ? "Float" : "Integer"), (Type[])null, (Type[])null)); PatchedExpressions++; } } if (rules.Count <= 0) { yield break; } NoLimitsPlugin.Log.LogInfo((object)("LINEAR " + __originalMethod.DeclaringType.FullName + "." + __originalMethod.Name + " expressions=" + rules.Count)); foreach (Rule item in rules) { NoLimitsPlugin.Log.LogInfo((object)("RULE item=" + item.Expr.Count.Item.Name + " site=" + __originalMethod.DeclaringType.FullName + "." + __originalMethod.Name + " slope=" + item.Expr.Slope + " offset=" + item.Expr.Offset)); } } } internal static int PatchedExpressions; private static readonly HashSet<string> NativeLinear = new HashSet<string> { "Crowbar", "NearbyDamageBonus", "FragileDamageBonus", "BossDamageBonus", "CritDamage", "ShinyPearl", "AllStatBoost", "EquipmentMagazine", "StrengthenBurn", "DroneUpgradeHidden", "IncreaseHealing", "RepeatHeal" }; private static readonly Dictionary<Type, FieldInfo> Behaviors = new Dictionary<Type, FieldInfo>(); private static readonly Dictionary<FieldInfo, FieldInfo> Cached = new Dictionary<FieldInfo, FieldInfo>(); private static bool Allowed(ItemDef item) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 if (DifficultyManager.Active && Rules.Enabled(Module.Items) && Object.op_Implicit((Object)(object)item) && !item.hidden) { return (int)item.tier != 5; } return false; } internal static float Float(float original, int count, float offset, ItemDef item) { if (Allowed(item) && count > 1) { return (float)Math.Min(3.4028234663852886E+38, (double)original + (double)offset * ((double)count - 1.0)); } return original; } internal static double Double(double original, int count, double offset, ItemDef item) { if (Allowed(item) && count > 1) { return original + offset * ((double)count - 1.0); } return original; } internal static int Integer(int original, int count, int offset, ItemDef item) { if (Allowed(item) && count > 1) { return (int)Math.Min(2147483647L, original + (long)offset * (long)(count - 1)); } return original; } private static int Local(CodeInstruction code, bool store) { OpCode opcode = code.opcode; if (store) { if (opcode == OpCodes.Stloc_0) { return 0; } if (opcode == OpCodes.Stloc_1) { return 1; } if (opcode == OpCodes.Stloc_2) { return 2; } if (opcode == OpCodes.Stloc_3) { return 3; } if (opcode != OpCodes.Stloc && opcode != OpCodes.Stloc_S) { return -1; } } else { if (opcode == OpCodes.Ldloc_0) { return 0; } if (opcode == OpCodes.Ldloc_1) { return 1; } if (opcode == OpCodes.Ldloc_2) { return 2; } if (opcode == OpCodes.Ldloc_3) { return 3; } if (opcode != OpCodes.Ldloc && opcode != OpCodes.Ldloc_S) { return -1; } } if (code.operand is LocalBuilder localBuilder) { return localBuilder.LocalIndex; } if (code.operand is LocalVariableInfo localVariableInfo) { return localVariableInfo.LocalIndex; } return Convert.ToInt32(code.operand); } internal static int LocalIndex(CodeInstruction code, bool store) { return Local(code, store); } private static bool Constant(CodeInstruction c, out double value, out bool floating, out bool wide) { value = 0.0; floating = false; wide = false; if (c.opcode == OpCodes.Ldc_R4 || c.opcode == OpCodes.Ldc_R8) { value = Convert.ToDouble(c.operand); floating = true; wide = c.opcode == OpCodes.Ldc_R8; return true; } if (c.opcode == OpCodes.Ldc_I4 || c.opcode == OpCodes.Ldc_I4_S) { value = Convert.ToDouble(c.operand); return true; } if (c.opcode == OpCodes.Ldc_I4_M1) { value = -1.0; return true; } short value2 = c.opcode.Value; OpCode ldc_I4_ = OpCodes.Ldc_I4_0; if (value2 >= ldc_I4_.Value) { short value3 = c.opcode.Value; OpCode ldc_I4_2 = OpCodes.Ldc_I4_8; if (value3 <= ldc_I4_2.Value) { short value4 = c.opcode.Value; OpCode ldc_I4_3 = OpCodes.Ldc_I4_0; value = value4 - ldc_I4_3.Value; return true; } } return false; } private static Expr Parse(List<CodeInstruction> codes, ref int cursor, Dictionary<int, Count> locals, Type owner, int depth) { if (cursor < 0 || depth > 12) { return null; } int num = cursor; CodeInstruction val = codes[cursor--]; if (Constant(val, out var value, out var floating, out var wide)) { Expr expr = new Expr(); expr.Offset = value; expr.Start = num; expr.Floating = floating; expr.Double = wide; return expr; } int num2 = Local(val, store: false); if (num2 >= 0 && locals.TryGetValue(num2, out var value2)) { Expr expr2 = new Expr(); expr2.Count = value2; expr2.Slope = 1.0; expr2.Start = num; return expr2; } MethodInfo methodInfo = val.operand as MethodInfo; if (methodInfo != null && methodInfo.DeclaringType == typeof(Inventory) && methodInfo.Name.StartsWith("GetItemCount", StringComparison.Ordinal) && cursor >= 0) { FieldInfo fieldInfo = codes[cursor].operand as FieldInfo; if (fieldInfo != null && fieldInfo.FieldType == typeof(ItemDef)) { int num3 = ReferenceStart(codes, cursor - 1, 0); if (num3 >= 0) { Count count = new Count(); count.Item = fieldInfo; count.Key = "inline:" + fieldInfo.ToString() + ":" + num3; count.Load = codes.GetRange(num3, num - num3 + 1).Select(Clone).ToList(); value2 = count; cursor = num3 - 1; Expr expr3 = new Expr(); expr3.Count = value2; expr3.Slope = 1.0; expr3.Start = num3; return expr3; } } } if (val.opcode == OpCodes.Conv_R4 || val.opcode == OpCodes.Conv_R8 || val.opcode == OpCodes.Conv_I4 || val.opcode == OpCodes.Conv_U4) { Expr expr4 = Parse(codes, ref cursor, locals, owner, depth + 1); if (expr4 != null) { expr4.Floating |= val.opcode == OpCodes.Conv_R4 || val.opcode == OpCodes.Conv_R8; expr4.Double |= val.opcode == OpCodes.Conv_R8; } return expr4; } FieldInfo fieldInfo2 = val.operand as FieldInfo; if (val.opcode == OpCodes.Ldfld && fieldInfo2 != null && fieldInfo2.FieldType == typeof(int)) { FieldInfo value3 = null; int num4 = -1; if (fieldInfo2.Name == "stack" && Behaviors.TryGetValue(owner, out value3) && cursor >= 0 && codes[cursor].opcode == OpCodes.Ldarg_0) { num4 = cursor--; } else if (Cached.TryGetValue(fieldInfo2, out value3) && cursor >= 1 && codes[cursor].opcode == OpCodes.Ldflda && codes[cursor - 1].opcode == OpCodes.Ldarg_0) { num4 = cursor - 1; cursor -= 2; } if (value3 != null && num4 >= 0) { Count count2 = new Count(); count2.Item = value3; count2.Key = fieldInfo2.ToString(); count2.Load = codes.GetRange(num4, num - num4 + 1).Select(Clone).ToList(); value2 = count2; Expr expr5 = new Expr(); expr5.Count = value2; expr5.Slope = 1.0; expr5.Start = num4; return expr5; } } if (val.opcode != OpCodes.Add && val.opcode != OpCodes.Sub && val.opcode != OpCodes.Mul && val.opcode != OpCodes.Div) { return null; } Expr expr6 = Parse(codes, ref cursor, locals, owner, depth + 1); Expr expr7 = Parse(codes, ref cursor, locals, owner, depth + 1); if (expr7 == null || expr6 == null || (expr7.Count != null && expr6.Count != null && expr7.Count.Key != expr6.Count.Key)) { return null; } Expr expr8 = new Expr(); expr8.Count = expr7.Count ?? expr6.Count; expr8.Start = expr7.Start; expr8.Floating = expr7.Floating || expr6.Floating; expr8.Double = expr7.Double || expr6.Double; Expr expr9 = expr8; if (val.opcode == OpCodes.Add) { expr9.Slope = expr7.Slope + expr6.Slope; expr9.Offset = expr7.Offset + expr6.Offset; } else if (val.opcode == OpCodes.Sub) { expr9.Slope = expr7.Slope - expr6.Slope; expr9.Offset = expr7.Offset - expr6.Offset; } else if (val.opcode == OpCodes.Mul) { if (expr7.Slope != 0.0 && expr6.Slope != 0.0) { return null; } expr9.Slope = expr7.Slope * expr6.Offset + expr6.Slope * expr7.Offset; expr9.Offset = expr7.Offset * expr6.Offset; } else { if (expr6.Slope != 0.0 || expr6.Offset == 0.0) { return null; } expr9.Slope = expr7.Slope / expr6.Offset; expr9.Offset = expr7.Offset / expr6.Offset; } return expr9; } private static int ReferenceStart(List<CodeInstruction> codes, int end, int depth) { if (end < 0 || depth > 5) { return -1; } CodeInstruction val = codes[end]; if (val.opcode == OpCodes.Ldarg_0 || val.opcode == OpCodes.Ldarg_1 || val.opcode == OpCodes.Ldarg_2 || val.opcode == OpCodes.Ldarg_3 || val.opcode == OpCodes.Ldarg || val.opcode == OpCodes.Ldarg_S || Local(val, store: false) >= 0) { return end; } if (val.opcode == OpCodes.Ldfld || val.opcode == OpCodes.Ldflda) { return ReferenceStart(codes, end - 1, depth + 1); } MethodInfo methodInfo = val.operand as MethodInfo; if (methodInfo != null && !methodInfo.IsStatic && methodInfo.GetParameters().Length == 0 && methodInfo.IsSpecialName) { return ReferenceStart(codes, end - 1, depth + 1); } return -1; } private static CodeInstruction Clone(CodeInstruction c) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return new CodeInstruction(c.opcode, c.operand); } } internal static class ChestLootManager { private sealed class OptionState { internal int Total; internal int Index; internal OptionState Previous; } [HarmonyPatch(typeof(ChestBehavior), "BaseItemDrop")] private static class MultiDrop { private static void Prefix(ChestBehavior __instance) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (DifficultyManager.Server && Rules.Enabled(Module.Loot) && !(__instance.currentPickup.pickupIndex == PickupIndex.none) && __instance.dropCount >= 1 && !fixedSingle) { __instance.dropCount = Count(); } } } [HarmonyPatch(typeof(ChestBehavior), "BaseItemOrbSpawn")] private static class PhysicalDrops { private static bool Prefix(ChestBehavior __instance) { if (!DifficultyManager.Server || !Rules.Enabled(Module.Loot)) { return true; } AccessTools.Method(typeof(ChestBehavior), "BaseItemDrop", (Type[])null, (Type[])null).Invoke(__instance, null); return false; } } [HarmonyPatch(typeof(OptionChestBehavior), "ItemDrop")] private static class OptionDrops { private static void Prefix(OptionChestBehavior __instance, out OptionState __state) { __state = null; if (DifficultyManager.Server && Rules.Enabled(Module.Loot) && option == null && AccessTools.Field(typeof(OptionChestBehavior), "generatedPickups").GetValue(__instance) is List<UniquePickup> { Count: not 0 }) { __state = new OptionState { Total = Count(), Previous = option }; option = __state; } } private static void Postfix(OptionChestBehavior __instance, OptionState __state) { if (__state == null) { return; } try { for (int i = 1; i < __state.Total; i++) { __state.Index = i; __instance.Roll(); __instance.ItemDrop(); } } finally { option = __state.Previous; } } private static Exception Finalizer(Exception __exception, OptionState __state) { if (__state != null) { option = __state.Previous; } return __exception; } } [HarmonyPatch(typeof(PickupDropletController), "CreatePickupDroplet", new Type[] { typeof(CreatePickupInfo), typeof(Vector3), typeof(Vector3) })] private static class OptionSpread { private static void Prefix(CreatePickupInfo __0, ref Vector3 __1, ref Vector3 __2) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (option != null && __0.pickerOptions != null && option.Total > 1) { Quaternion val = Quaternion.AngleAxis(360f * (float)option.Index / (float)option.Total, Vector3.up); __1 += val * Vector3.forward * 0.7f; __2 = val * __2; } } } [HarmonyPatch(typeof(ChestBehavior), "DelusionItemDrop", new Type[] { typeof(DelusionChestController) })] private static class DelusionDrops { private static void Prefix(DelusionChestController __0, out int __state) { __state = ((DifficultyManager.Server && Rules.Enabled(Module.Loot) && Object.op_Implicit((Object)(object)__0) && __0.isDelusionSelected && __0.IsSelectedCorrectly()) ? Count() : 0); } private static void Postfix(ChestBehavior __instance, int __state) { ExtraDelusionDrops(__instance, __state); } } [HarmonyPatch(typeof(RouletteChestController), "EjectPickupServer")] private static class RouletteDrops { private static void Prefix(RouletteChestController __instance, UniquePickup __0, out int __state) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) __state = 0; if (DifficultyManager.Server && Rules.Enabled(Module.Loot) && !rouletteExtra && !((UniquePickup)(ref __0)).Equals(UniquePickup.none)) { __state = Count(); __instance.dropCount = 1; } } private static void Postfix(RouletteChestController __instance, int __state) { //IL_00aa: 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_002b: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) if (__state <= 1) { return; } rouletteExtra = true; try { Xoroshiro128Plus val = (Xoroshiro128Plus)AccessTools.Field(typeof(RouletteChestController), "rng").GetValue(__instance); for (int i = 1; i < __state; i++) { UniquePickup val2 = __instance.dropTable.GeneratePickup(val); Quaternion rotation = __instance.ejectionTransform.rotation; try { __instance.ejectionTransform.rotation = Quaternion.AngleAxis(360f * (float)i / (float)__state, Vector3.up) * rotation; AccessTools.Method(typeof(RouletteChestController), "EjectPickupServer", (Type[])null, (Type[])null).Invoke(__instance, new object[1] { val2 }); } finally { __instance.ejectionTransform.rotation = rotation; } } } finally { rouletteExtra = false; } } } [ThreadStatic] private static bool fixedSingle; [ThreadStatic] private static OptionState option; [ThreadStatic] private static bool rouletteExtra; private static int Count() { NoLimitsConfig settings = NoLimitsPlugin.Settings; return RandomSource.Inclusive(Math.Min(settings.ChestDropMin.Value, settings.ChestDropMax.Value), Math.Max(settings.ChestDropMin.Value, settings.ChestDropMax.Value)); } private static void ExtraDelusionDrops(ChestBehavior chest, int count) { if (count <= 1) { return; } bool flag = fixedSingle; fixedSingle = true; try { for (int i = 1; i < count; i++) { chest.Roll(); chest.dropCount = 1; AccessTools.Method(typeof(ChestBehavior), "BaseItemDrop", (Type[])null, (Type[])null).Invoke(chest, null); } } finally { fixedSingle = flag; } } } internal static class ChestSpawnManager { [HarmonyPatch(typeof(ClassicStageInfo), "RebuildCards")] private static class ChestCards { private static void Prefix(ref DirectorCardCategorySelection __1) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Expected O, but got Unknown //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) if (!DifficultyManager.Server || !Rules.Enabled(Module.Chests) || !DifficultyManager.Stage || !Object.op_Implicit((Object)(object)__1) || !ContentPool.Ready) { return; } DirectorCardCategorySelection val = ScriptableObject.CreateInstance<DirectorCardCategorySelection>(); val.CopyFrom(__1); val.categories = (Category[])val.categories.Clone(); int num = val.FindCategoryIndexByName("Chests"); if (num < 0) { num = val.AddCategory("Chests", 1f); } HashSet<SpawnCard> hashSet = new HashSet<SpawnCard>(); Category[] categories = val.categories; for (int i = 0; i < categories.Length; i++) { Category val2 = categories[i]; DirectorCard[] cards = val2.cards; foreach (DirectorCard val3 in cards) { hashSet.Add(val3.GetSpawnCard()); } } List<DirectorCard> list = new List<DirectorCard>(ContentPool.Chests); list.AddRange(QualityCompatibility.ChestCards); foreach (DirectorCard item in list) { string name = ((Object)item.GetSpawnCard()).name; int num2; switch (name) { default: num2 = ((name == "iscHollowChest") ? 1 : 0); break; case "iscChest1": case "iscChest2": case "iscEquipmentBarrel": case "iscCategoryChestDamage": case "iscCategoryChestHealing": case "iscCategoryChestUtility": case "iscCategoryChest2Damage": case "iscCategoryChest2Healing": case "iscCategoryChest2Utility": case "iscLunarChest": case "iscVoidChest": case "iscCasinoChest": num2 = 1; break; } bool flag = (byte)num2 != 0; bool flag2 = name == "iscGoldChest" && NoLimitsPlugin.Settings.AllowLegendaryChestsEverywhere.Value; if ((flag || flag2 || QualityCompatibility.IsQualityChest(item.GetSpawnCard())) && item.IsAvailable() && hashSet.Add(item.GetSpawnCard())) { val.AddCard(num, item); } } OwnedSelection ownedSelection = (Object.op_Implicit((Object)(object)ClassicStageInfo.instance) ? ((Component)ClassicStageInfo.instance).gameObject.AddComponent<OwnedSelection>() : null); if (Object.op_Implicit((Object)(object)ownedSelection)) { ownedSelection.Selection = val; } Dictionary<SpawnCard, SpawnCard> dictionary = new Dictionary<SpawnCard, SpawnCard>(); for (int k = 0; k < val.categories.Length; k++) { DirectorCard[] array = (DirectorCard[])val.categories[k].cards.Clone(); for (int l = 0; l < array.Length; l++) { DirectorCard val4 = array[l]; SpawnCard spawnCard = val4.GetSpawnCard(); if (!Object.op_Implicit((Object)(object)spawnCard) || !Object.op_Implicit((Object)(object)spawnCard.prefab) || (!Object.op_Implicit((Object)(object)spawnCard.prefab.GetComponent<ChestBehavior>()) && !Object.op_Implicit((Object)(object)spawnCard.prefab.GetComponent<OptionChestBehavior>()) && !Object.op_Implicit((Object)(object)spawnCard.prefab.GetComponent<RouletteChestController>()))) { continue; } if (!dictionary.TryGetValue(spawnCard, out var value)) { value = Object.Instantiate<SpawnCard>(spawnCard); ((Object)value).name = ((Object)spawnCard).name; value.directorCreditCost = Math.Max(1, (int)Math.Ceiling((double)spawnCard.directorCreditCost / (double)NoLimitsPlugin.Settings.ChestCreditMultiplier.Value)); dictionary.Add(spawnCard, value); if (Object.op_Implicit((Object)(object)ownedSelection)) { ownedSelection.Cards.Add(value); } } int num3 = l; DirectorCard val5 = new DirectorCard(); val5.spawnCard = value; val5.selectionWeight = val4.selectionWeight; val5.minimumStageCompletions = val4.minimumStageCompletions; val5.spawnDistance = val4.spawnDistance; val5.preventOverhead = val4.preventOverhead; val5.requiredUnlockableDef = val4.requiredUnlockableDef; val5.forbiddenUnlockableDef = val4.forbiddenUnlockableDef; array[num3] = val5; } val.categories[k].cards = array; } __1 = val; } } private sealed class OwnedSelection : MonoBehaviour { internal DirectorCardCategorySelection Selection; internal readonly List<SpawnCard> Cards = new List<SpawnCard>(); private void OnDestroy() { if (Object.op_Implicit((Object)(object)Selection)) { Object.Destroy((Object)(object)Selection); } foreach (SpawnCard card in Cards) { if (Object.op_Implicit((Object)(object)card)) { Object.Destroy((Object)(object)card); } } } } internal static void Install() { } internal static void Uninstall() { } } internal static class ContentPool { internal static readonly HashSet<string> BossBodies = new HashSet<string>(StringComparer.Ordinal) { "BeetleQueen2Body", "VagrantBody", "TitanBody", "ClayBossBody", "MagmaWormBody", "ElectricWormBody", "ImpBossBody", "GravekeeperBody", "RoboBallBossBody", "GrandParentBody", "MegaConstructBody", "ScavBody", "VoidMegaCrabBody" }; private static readonly HashSet<string> MonsterBodies = new HashSet<string>(StringComparer.Ordinal) { "BeetleBody", "BeetleGuardBody", "LemurianBody", "LemurianBruiserBody", "WispBody", "GreaterWispBody", "GolemBody", "BellBody", "BisonBody", "ImpBody", "ClayBruiserBody", "ClayGrenadierBody", "JellyfishBody", "MiniMushroomBody", "ParentBody", "RoboBallMiniBody", "VultureBody", "HermitCrabBody", "GupBody", "GipBody", "GeepBody", "VerminBody", "FlyingVerminBody", "VoidBarnacleBody", "VoidJailerBody", "LunarGolemBody", "LunarWispBody", "LunarExploderBody", "ChildBody" }; internal static readonly List<DirectorCard> Cards = new List<DirectorCard>(); internal static readonly List<DirectorCard> Chests = new List<DirectorCard>(); internal static readonly Dictionary<string, string> Sources = new Dictionary<string, string>(StringComparer.Ordinal); private static readonly string[] StoryBodies = new string[8] { "Brother", "VoidRaidCrab", "FalseSonBoss", "SolusWing", "SolusHeart", "Providence", "ScavLunar", "ReaperMalachiteBoss" }; private static readonly HashSet<string> SpecialScenes = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "moon", "moon2", "voidraid", "meridian", "solutionalhaunt", "solusweb", "computationalexchange", "limbo", "arena", "goldshores", "artifactworld", "champrush", "sanctum" }; private static readonly List<AsyncOperationHandle> Handles = new List<AsyncOperationHandle>(); internal static bool Ready; internal static CharacterBody Body(SpawnCard card) { if (!Object.op_Implicit((Object)(object)card) || !Object.op_Implicit((Object)(object)card.prefab)) { return null; } CharacterMaster component = card.prefab.GetComponent<CharacterMaster>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.bodyPrefab)) { return null; } return component.bodyPrefab.GetComponent<CharacterBody>(); } internal static bool IsOrdinaryBoss(SpawnCard card) { CharacterBody val = Body(card); if (Object.op_Implicit((Object)(object)val)) { return BossBodies.Contains(((Object)val).name); } return false; } internal static bool TeleporterEligible(DirectorCard card) { SpawnCard spawnCard = card.GetSpawnCard(); CharacterSpawnCard val = (CharacterSpawnCard)(object)((spawnCard is CharacterSpawnCard) ? spawnCard : null); if (Object.op_Implicit((Object)(object)val) && !val.forbiddenAsBoss && IsOrdinaryBoss((SpawnCard)(object)val)) { return card.IsAvailable(); } return false; } internal static IEnumerator Load() { HashSet<string> keys = new HashSet<string>(StringComparer.Ordinal); HashSet<string> stageCards = new HashSet<string>(StringComparer.Ordinal); List<string> stages = (from val7 in (IEnumerable<SceneDef>)(object)SceneCatalog.allSceneDefs where Object.op_Implicit((Object)(object)val7) && (int)val7.sceneType == 1 && !val7.isFinalStage && !SpecialScenes.Contains(val7.baseSceneName) && (val7.validForRandomSelection || (val7.stageOrder >= 1 && val7.stageOrder <= 5)) select val7.baseSceneName).Distinct().ToList(); foreach (IResourceLocator resourceLocator in Addressables.ResourceLocators) { foreach (object key2 in resourceLocator.Keys) { string s = key2 as string; if (s != null && s.StartsWith("RoR2/", StringComparison.Ordinal) && s.EndsWith(".asset", StringComparison.Ordinal)) { if (s.IndexOf("/csc", StringComparison.OrdinalIgnoreCase) >= 0 || s.IndexOf("/isc", StringComparison.OrdinalIgnoreCase) >= 0) { keys.Add(s); } if ((s.IndexOf("/dccs", StringComparison.OrdinalIgnoreCase) >= 0 || s.IndexOf("/dp", StringComparison.OrdinalIgnoreCase) >= 0) && s.IndexOf("Monsters", StringComparison.OrdinalIgnoreCase) >= 0 && s.IndexOf("UNUSED", StringComparison.OrdinalIgnoreCase) < 0 && stages.Any((string stage) => s.IndexOf("/" + stage + "/", StringComparison.OrdinalIgnoreCase) >= 0)) { stageCards.Add(s); } } } } HashSet<string> seenBodies = new HashSet<string>(); HashSet<string> seenChest = new HashSet<string>(); foreach (string key in keys.OrderBy<string, string>((string result) => result, StringComparer.Ordinal)) { AsyncOperationHandle<SpawnCard> handle = Addressables.LoadAssetAsync<SpawnCard>((object)key); yield return handle; Handles.Add(AsyncOperationHandle<SpawnCard>.op_Implicit(handle)); if ((int)handle.Status != 1 || !Object.op_Implicit((Object)(object)handle.Result)) { continue; } SpawnCard spawn = handle.Result; CharacterBody body = Body(spawn); bool specialized = ((Object)spawn).name.IndexOf("Karma", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)spawn).name.IndexOf("Barrage", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)spawn).name.IndexOf("Gold", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)spawn).name.IndexOf("LunarScav", StringComparison.OrdinalIgnoreCase) >= 0; if (Object.op_Implicit((Object)(object)body) && !specialized && (BossBodies.Contains(((Object)body).name) || MonsterBodies.Contains(((Object)body).name)) && seenBodies.Add(((Object)body).name)) { if (((Object)spawn).name.IndexOf("Gold", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)spawn).name.IndexOf("LunarScav", StringComparison.OrdinalIgnoreCase) >= 0) { seenBodies.Remove(((Object)body).name); continue; } List<DirectorCard> cards = Cards; DirectorCard val = new DirectorCard(); val.spawnCard = spawn; val.selectionWeight = 1; val.minimumStageCompletions = 0; val.spawnDistance = (MonsterSpawnDistance)0; cards.Add(val); } if (Object.op_Implicit((Object)(object)spawn.prefab) && (Object.op_Implicit((Object)(object)spawn.prefab.GetComponent<ChestBehavior>()) || Object.op_Implicit((Object)(object)spawn.prefab.GetComponent<OptionChestBehavior>()) || Object.op_Implicit((Object)(object)spawn.prefab.GetComponent<RouletteChestController>())) && seenChest.Add(((Object)spawn).name)) { List<DirectorCard> chests = Chests; DirectorCard val2 = new DirectorCard(); val2.spawnCard = spawn; val2.selectionWeight = 1; val2.minimumStageCompletions = 0; chests.Add(val2); } } foreach (string address in stageCards.OrderBy<string, string>((string result) => result, StringComparer.Ordinal)) { if (address.IndexOf("/dccs", StringComparison.OrdinalIgnoreCase) >= 0) { AsyncOperationHandle<DirectorCardCategorySelection> handle2 = Addressables.LoadAssetAsync<DirectorCardCategorySelection>((object)address); yield return handle2; Handles.Add(AsyncOperationHandle<DirectorCardCategorySelection>.op_Implicit(handle2)); if ((int)handle2.Status == 1) { AddStageSelection(handle2.Result, address, seenBodies); } continue; } AsyncOperationHandle<DccsPool> handle3 = Addressables.LoadAssetAsync<DccsPool>((object)address); yield return handle3; Handles.Add(AsyncOperationHandle<DccsPool>.op_Implicit(handle3)); if ((int)handle3.Status != 1 || !Object.op_Implicit((Object)(object)handle3.Result)) { continue; } Category[] poolCategories = handle3.Result.poolCategories; foreach (Category val3 in poolCategories) { if (val3.alwaysIncluded != null) { PoolEntry[] alwaysIncluded = val3.alwaysIncluded; foreach (PoolEntry val4 in alwaysIncluded) { AddStageSelection(val4.dccs, address, seenBodies); } } if (val3.includedIfConditionsMet != null) { ConditionalPoolEntry[] includedIfConditionsMet = val3.includedIfConditionsMet; foreach (ConditionalPoolEntry val5 in includedIfConditionsMet) { AddStageSelection(((PoolEntry)val5).dccs, address, seenBodies); } } if (val3.includedIfNoConditionsMet != null) { PoolEntry[] includedIfNoConditionsMet = val3.includedIfNoConditionsMet; foreach (PoolEntry val6 in includedIfNoConditionsMet) { AddStageSelection(val6.dccs, address, seenBodies); } } } } Ready = true; NoLimitsPlugin.Log.LogInfo((object)("Discovered " + Cards.Count + " allowlisted ordinary enemy cards, " + Chests.Count + " chest cards.")); foreach (DirectorCard card in Cards) { NoLimitsPlugin.Log.LogInfo((object)("POOL " + ((Object)Body(card.GetSpawnCard())).name + " / " + ((Object)card.GetSpawnCard()).name + " boss=" + IsOrdinaryBoss(card.GetSpawnCard()))); } } private static void AddStageSelection(DirectorCardCategorySelection selection, string address, HashSet<string> seen) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)selection) || selection.categories == null) { return; } Category[] categories = selection.categories; for (int i = 0; i < categories.Length; i++) { Category val = categories[i]; DirectorCard[] cards = val.cards; foreach (DirectorCard val2 in cards) { if (val2 == null) { continue; } SpawnCard spawnCard = val2.GetSpawnCard(); CharacterSpawnCard val3 = (CharacterSpawnCard)(object)((spawnCard is CharacterSpawnCard) ? spawnCard : null); CharacterBody body = Body((SpawnCard)(object)val3); if (Object.op_Implicit((Object)(object)body) && !StoryBodies.Any((string prefix) => ((Object)body).name.StartsWith(prefix, StringComparison.Ordinal)) && ((Object)val3).name.IndexOf("Karma", StringComparison.OrdinalIgnoreCase) < 0 && ((Object)val3).name.IndexOf("Barrage", StringComparison.OrdinalIgnoreCase) < 0 && ((Object)val3).name.IndexOf("Gold", StringComparison.OrdinalIgnoreCase) < 0) { if (body.isChampion) { BossBodies.Add(((Object)body).name); } else { MonsterBodies.Add(((Object)body).name); } if (!Sources.ContainsKey(((Object)body).name)) { Sources[((Object)body).name] = address; } if (seen.Add(((Object)body).name)) { List<DirectorCard> cards2 = Cards; DirectorCard val4 = new DirectorCard(); val4.spawnCard = (SpawnCard)(object)val3; val4.selectionWeight = 1; val4.minimumStageCompletions = 0; val4.spawnDistance = val2.spawnDistance; val4.preventOverhead = val2.preventOverhead; val4.requiredUnlockable = val2.requiredUnlockable; val4.forbiddenUnlockable = val2.forbiddenUnlockable; val4.requiredUnlockableDef = val2.requiredUnlockableDef; val4.forbiddenUnlockableDef = val2.forbiddenUnlockableDef; cards2.Add(val4); NoLimitsPlugin.Log.LogInfo((object)("ALLOW body=" + ((Object)body).name + " card=" + ((Object)val3).name + " source=" + address)); } } } } } internal static void Dispose() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) foreach (AsyncOperationHandle handle in Handles) { AsyncOperationHandle current = handle; if (((AsyncOperationHandle)(ref current)).IsValid()) { Addressables.Release(current); } } Handles.Clear(); Cards.Clear(); Chests.Clear(); Ready = false; } } internal static class ContinuousItemRules { [HarmonyPatch(typeof(Inventory), "CalculateEquipmentCooldownScale")] private static class GearCooldown { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { int power = 0; MethodInfo pow = AccessTools.Method(typeof(Mathf), "Pow", new Type[2] { typeof(float), typeof(float) }, (Type[])null); foreach (CodeInstruction code in input) { if (CodeInstructionExtensions.Calls(code, pow)) { power++; if (power <= 2) { code.opcode = OpCodes.Call; code.operand = AccessTools.Method(typeof(ContinuousItemRules), (power == 1) ? "GearPower" : "GesturePower", (Type[])null, (Type[])null); } } yield return code; } if (power != 3) { throw new InvalidOperationException("Equipment cooldown formula changed: " + power); } } } [HarmonyPatch(typeof(CharacterBody), "RecalculateStats")] private static class Skills { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, ILGenerator generator) { List<CodeInstruction> codes = input.ToList(); Dictionary<int, string> counts = new Dictionary<int, string>(); Dictionary<int, List<CodeInstruction>> before = new Dictionary<int, List<CodeInstruction>>(); Dictionary<int, List<CodeInstruction>> after = new Dictionary<int, List<CodeInstruction>>(); for (int i = 1; i + 1 < codes.Count; i++) { FieldInfo fieldInfo = codes[i - 1].operand as FieldInfo; MethodInfo methodInfo = codes[i].operand as MethodInfo; int num = AffineItemRules.LocalIndex(codes[i + 1], store: true); if (fieldInfo != null && fieldInfo.FieldType == typeof(ItemDef) && methodInfo != null && methodInfo.DeclaringType == typeof(Inventory) && methodInfo.Name == "GetItemCountEffective" && num >= 0) { counts[num] = fieldInfo.Name; } } for (int j = 2; j < codes.Count; j++) { if (codes[j].opcode != OpCodes.Blt && codes[j].opcode != OpCodes.Blt_S) { continue; } int num2 = AffineItemRules.LocalIndex(codes[j - 1], store: false); if (num2 < 0 || !counts.TryGetValue(num2, out var value) || (value != "AlienHead" && value != "HalfAttackSpeedHalfCooldowns")) { continue; } Label label = (Label)codes[j].operand; int num3 = codes.FindIndex((CodeInstruction c) => c.labels.Contains(label)); if (num3 < 0) { continue; } float num4 = ((value == "AlienHead") ? 0.75f : 0.5f); for (int num5 = num3; num5 < j; num5++) { if (codes[num5].opcode == OpCodes.Ldc_R4 && Math.Abs((float)codes[num5].operand - num4) < 1E-05f) { after[num5] = new List<CodeInstruction> { new CodeInstruction(OpCodes.Ldloc, (object)(short)num2), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "LoopFactor", (Type[])null, (Type[])null)) }; before[j] = new List<CodeInstruction> { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "LoopBound", (Type[])null, (Type[])null)) }; break; } } } MethodInfo clamp = AccessTools.Method(typeof(Mathf), "Clamp", new Type[3] { typeof(float), typeof(float), typeof(float) }, (Type[])null); for (int i2 = 0; i2 < codes.Count; i2++) { if (codes[i2].opcode == OpCodes.Ldc_R4) { float num6 = (float)codes[i2].operand; string skillItem = ((Math.Abs(num6 - 2f / 3f) < 1E-06f) ? "UtilitySkillMagazine" : ((Math.Abs(num6 - 0.67f) < 1E-06f) ? "EquipmentMagazineVoid" : null)); int num7 = ((skillItem == null) ? (-1) : (from p in counts where p.Value == skillItem select p.Key).DefaultIfEmpty(-1).First()); if (num7 >= 0) { after[i2] = new List<CodeInstruction> { new CodeInstruction(OpCodes.Ldloc, (object)(short)num7), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "LoopFactor", (Type[])null, (Type[])null)) }; } } if (CodeInstructionExtensions.Calls(codes[i2], clamp) && codes.Skip(Math.Max(0, i2 - 5)).Take(Math.Min(5, i2)).Any((CodeInstruction c) => c.operand is FieldInfo && ((FieldInfo)c.operand).Name == "minCooldownCoefficient")) { LocalBuilder localBuilder = generator.DeclareLocal(typeof(float)); LocalBuilder localBuilder2 = generator.DeclareLocal(typeof(float)); LocalBuilder localBuilder3 = generator.DeclareLocal(typeof(float)); before[i2] = new List<CodeInstruction> { new CodeInstruction(OpCodes.Stloc, (object)localBuilder), new CodeInstruction(OpCodes.Stloc, (object)localBuilder2), new CodeInstruction(OpCodes.Dup, (object)null), new CodeInstruction(OpCodes.Stloc, (object)localBuilder3), new CodeInstruction(OpCodes.Ldloc, (object)localBuilder2), new CodeInstruction(OpCodes.Ldloc, (object)localBuilder) }; after[i2] = new List<CodeInstruction> { new CodeInstruction(OpCodes.Ldloc, (object)localBuilder3), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "Unclamp", (Type[])null, (Type[])null)) }; } if (before.TryGetValue(i2, out var insert)) { foreach (CodeInstruction item in insert) { yield return item; } } yield return codes[i2]; if (!after.TryGetValue(i2, out insert)) { continue; } foreach (CodeInstruction item2 in insert) { yield return item2; } } } } [HarmonyPatch] private static class Convergence { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(HoldoutZoneController).GetNestedType("FocusConvergenceController", BindingFlags.NonPublic), "DoUpdate", (Type[])null, (Type[])null); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { foreach (CodeInstruction c in input) { yield return c; if (c.operand is FieldInfo && ((FieldInfo)c.operand).Name == "cap") { yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "Cap", (Type[])null, (Type[])null)); } } } } [HarmonyPatch] private static class Corpsebloom { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(HealthComponent).GetNestedType("RepeatHealComponent", BindingFlags.NonPublic), "RecalculateStats", (Type[])null, (Type[])null); } private static void Postfix(object __instance) { if (Active) { Type type = __instance.GetType(); object? value = AccessTools.Field(type, "body").GetValue(__instance); CharacterBody val = (CharacterBody)((value is CharacterBody) ? value : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.inventory)) { AccessTools.Field(type, "healthFractionToRestorePerSecond").SetValue(__instance, 0.1f * (float)Math.Max(1, val.inventory.GetItemCountEffective(Items.RepeatHeal))); } } } } [HarmonyPatch(typeof(DroneShockDamageBodyBehavior), "get_duration")] private static class ShockAura { private static void Postfix(DroneShockDamageBodyBehavior __instance, ref float __result) { if (Active) { __result = 15f / (float)Math.Max(1, ((BaseItemBodyBehavior)__instance).stack); } } } [HarmonyPatch(typeof(CharacterBody), "AddTimedBuff", new Type[] { typeof(BuffDef), typeof(float) })] private static class Stealth { private static void Prefix(CharacterBody __instance, BuffDef __0, ref float __1) { if (!Active) { return; } if ((Object)(object)__0 == (Object)(object)Buffs.Nullified) { __1 = NativeProcOverflow.RootDuration(__1); } else { if (!Object.op_Implicit((Object)(object)__instance.inventory)) { return; } if ((Object)(object)__0 == (Object)(object)Buffs.LowHealthOrbSpawnerCooldown) { __1 /= Math.Max(1, __instance.inventory.GetItemCountEffective(Items.LowHealthOrbSpawner)); } else if (!((Object)(object)__0 != (Object)(object)Buffs.PhasingCooldown)) { int itemCountEffective = __instance.inventory.GetItemCountEffective(Items.Phasing); if (itemCountEffective > 0) { __1 = 35f / (float)itemCountEffective; } } } } } [HarmonyPatch(typeof(LunarSunBehavior), "GetMaxProjectiles")] private static class OrbitCount { private static void Postfix(Inventory __0, ref int __result) { if (Active) { __result = (int)Math.Min(2147483647L, 3L * (long)__0.GetItemCountEffective(Items.LunarSun)); } } } [HarmonyPatch(typeof(AttackSpeedPerNearbyCollider), "UpdateValues")] private static class NearbyCapacity { private static void Postfix(AttackSpeedPerNearbyCollider __instance, int __0) { if (Active) { AccessTools.Field(typeof(AttackSpeedPerNearbyCollider), "maxCharacterCount").SetValue(__instance, (int)Math.Min(2147483647L, 3L * (long)Math.Max(0, __0))); } } } [HarmonyPatch] private static class HyperbolicProcCurves { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(GlobalEventManager), "ProcessHitEnemy", (Type[])null, (Type[])null); yield return AccessTools.Method(typeof(SetStateOnHurt), "OnTakeDamageServer", (Type[])null, (Type[])null); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, MethodBase __originalMethod) { MethodInfo conversion = AccessTools.Method(typeof(Util), "ConvertAmplificationPercentageIntoReductionPercentage", (Type[])null, (Type[])null); bool stun = __originalMethod.DeclaringType == typeof(SetStateOnHurt); bool scaled = false; foreach (CodeInstruction code in input) { if (CodeInstructionExtensions.Calls(code, conversion)) { if (stun) { yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null); } code.opcode = OpCodes.Call; code.operand = AccessTools.Method(typeof(ContinuousItemRules), stun ? "StunChance" : "RawChance", (Type[])null, (Type[])null); } MethodInfo call = code.operand as MethodInfo; if (stun && !scaled && call != null && call.DeclaringType == typeof(SetStateOnHurt) && call.Name == "SetStun") { yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "StunDuration", (Type[])null, (Type[])null)); scaled = true; } yield return code; } } } [HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")] private static class ArmorPlate { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, ILGenerator generator) { List<CodeInstruction> codes = input.ToList(); MethodInfo max = AccessTools.Method(typeof(Mathf), "Max", new Type[2] { typeof(float), typeof(float) }, (Type[])null); for (int i = 0; i < codes.Count; i++) { bool plate = CodeInstructionExtensions.Calls(codes[i], max) && codes.Skip(Math.Max(0, i - 9)).Take(Math.Min(9, i)).Any((CodeInstruction c) => c.operand is FieldInfo && ((FieldInfo)c.operand).Name == "armorPlate"); LocalBuilder raw = null; if (plate) { raw = generator.DeclareLocal(typeof(float)); yield return new CodeInstruction(OpCodes.Dup, (object)null); yield return new CodeInstruction(OpCodes.Stloc, (object)raw); } yield return codes[i]; if (plate) { yield return new CodeInstruction(OpCodes.Ldloc, (object)raw); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "FlatPlate", (Type[])null, (Type[])null)); } } } } [HarmonyPatch(typeof(GoldTitanManager), "TryStartChannelingTitansServer")] private static class Titan { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { MethodInfo pow = AccessTools.Method(typeof(Mathf), "Pow", new Type[2] { typeof(float), typeof(float) }, (Type[])null); foreach (CodeInstruction c in input) { if (CodeInstructionExtensions.Calls(c, pow)) { c.opcode = OpCodes.Call; c.operand = AccessTools.Method(typeof(ContinuousItemRules), "TitanPower", (Type[])null, (Type[])null); } yield return c; } } } [HarmonyPatch(typeof(CharacterBody), "RemoveBuffInternal")] private static class Medkit { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { bool medkit = false; foreach (CodeInstruction c in input) { FieldInfo f = c.operand as FieldInfo; if (f != null && f.DeclaringType == typeof(Items) && f.Name == "Medkit") { medkit = true; } yield return c; if (medkit && c.opcode == OpCodes.Ldc_R4 && (float)c.operand == 20f) { yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "MedkitFlat", (Type[])null, (Type[])null)); medkit = false; } } } } [HarmonyPatch(typeof(DotController), "InflictDot", new Type[] { typeof(GameObject), typeof(GameObject), typeof(HurtBox), typeof(ProcChainMask), typeof(DotIndex), typeof(float), typeof(float), typeof(uint?) })] private static class GuaranteedBleed { private static void Prefix(GameObject __1, DotIndex __4, ref float __6) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) DamageInfo currentInfo = NativeProcOverflow.CurrentInfo; if (Active && DifficultyManager.Server && (int)__4 == 0 && currentInfo != null && !((Object)(object)currentInfo.attacker != (Object)(object)__1) && Object.op_Implicit((Object)(object)__1)) { CharacterBody component = __1.GetComponent<CharacterBody>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.inventory) && (DamageTypeCombo.op_Implicit(currentInfo.damageType & DamageTypeCombo.op_Implicit((DamageType)1024)) != 0 || (currentInfo.crit && component.inventory.GetItemCountEffective(Items.BleedOnHitAndExplode) > 0))) { __6 *= NativeProcOverflow.ActivationCount(nativeResult: true, component.bleedChance * currentInfo.procCoefficient, component.master); } } } } [HarmonyPatch(typeof(MushroomBodyBehavior), "FixedUpdate")] private static class MushroomRadius { private static void Postfix(MushroomBodyBehavior __instance) { if (Active && DifficultyManager.Server && ((BaseItemBodyBehavior)__instance).stack > 1) { object? value = AccessTools.Field(typeof(MushroomBodyBehavior), "mushroomHealingWard").GetValue(__instance); HealingWard val = (HealingWard)((value is HealingWard) ? value : null); if (Object.op_Implicit((Object)(object)val)) { val.Networkradius += 1.5f * (float)(((BaseItemBodyBehavior)__instance).stack - 1); } } } } [HarmonyPatch(typeof(IcicleAuraController), "get_maxIcicleCount")] private static class IcicleMaximum { private static void Postfix(IcicleAuraController __instance, ref int __result) { if (Active && Object.op_Implicit((Object)(object)__instance.owner)) { CharacterBody component = __instance.owner.GetComponent<CharacterBody>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.inventory)) { int itemCountEffective = component.inventory.GetItemCountEffective(Items.Icicle); __result = (int)Math.Min(2147483647L, __result + (long)Math.Max(0, itemCountEffective - 1) * (long)(__instance.baseIcicleMax - __instance.icicleMaxPerStack)); } } } } [HarmonyPatch(typeof(OnLevelUpFreeUnlockBehavior), "LevelThresholdCheck")] private static class BondLifetime { private static bool Prefix() { return !Active; } } [HarmonyPatch(typeof(CharacterMaster), "GiveMoneyWithOnLevelUpFreeUnlock")] private static class BondScaling { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { bool scaling = false; foreach (CodeInstruction c in input) { if (c.opcode == OpCodes.Conv_U8) { c.opcode = OpCodes.Call; c.operand = AccessTools.Method(typeof(ContinuousItemRules), "BondExperience", (Type[])null, (Type[])null); } yield return c; FieldInfo field = c.operand as FieldInfo; if (field != null && field.DeclaringType == typeof(CharacterMaster) && field.Name == "maxStacks") { yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "StackCap", (Type[])null, (Type[])null)); } if (field != null && field.DeclaringType == typeof(CharacterMaster) && field.Name == "stackingBonus") { scaling = true; } if (scaling && c.opcode == OpCodes.Add) { yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "BondFactor", (Type[])null, (Type[])null)); scaling = false; } } } } [HarmonyPatch(typeof(CharacterBody), "AddFreeChestBuff")] private static class BondUnlocks { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { foreach (CodeInstruction c in input) { yield return c; if (c.opcode == OpCodes.Ldc_I4_3) { yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "Cap", (Type[])null, (Type[])null)); } } } } [HarmonyPatch(typeof(LowHealthOrbSpawnerBehavior), "GetRollChanceNormalized")] private static class RestorationChance { private static void Postfix(LowHealthOrbSpawnerBehavior __instance, ref float __result) { if (Active) { __result = 0.1f * (float)((BaseItemBodyBehavior)__instance).stack; } } } [HarmonyPatch(typeof(LowHealthOrbSpawnerBehavior), "ProcessRestoration")] private static class RestorationCost { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { List<CodeInstruction> codes = input.ToList(); int found = 0; for (int i = 0; i < codes.Count; i++) { yield return codes[i]; if (codes[i].opcode == OpCodes.Ldc_I4 && (int)codes[i].operand == int.MaxValue && i + 1 < codes.Count && codes[i + 1].operand is MethodInfo && ((MethodInfo)codes[i + 1].operand).Name == "set_maxToTransform") { yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ContinuousItemRules), "ConsumeOne", (Type[])null, (Type[])null)); found++; } } if (found != 1) { throw new InvalidOperationException("Dream Crucible consume boundary changed: " + found); } } } private static bool Active { get { if (DifficultyManager.Active) { return Rules.Enabled(Module.Items); } return false; } } internal static void Install() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(Stats); } internal static void Uninstall() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown RecalculateStatsAPI.GetStatCoefficients -= new StatHookEventHandler(Stats); } private static void Stats(CharacterBody body, StatHookEventArgs args) { if (Active && Object.op_Implicit((Object)(object)body.inventory)) { ItemDef[] array = (ItemDef[])(object)new ItemDef[3] { Items.AttackSpeedOnCrit, Items.HealOnCrit, Items.BleedOnHitAndExplode }; foreach (ItemDef val in array) { args.critAdd += 5f * (float)Math.Max(0, body.inventory.GetItemCountEffective(val) - 1); } if (body.HasBuff(Buffs.CloakSpeed)) { args.moveSpeedMultAdd += 0.4f * (float)Math.Max(0, body.inventory.GetItemCountEffective(Items.Phasing) - 1); } } } internal static float LinearCooldown(float basis, float stacks) { if (!Active) { return Mathf.Pow(basis, stacks); } if (stacks <= 0f) { return 1f; } return (float)(1.0 / (1.0 + (1.0 - (double)basis) / (double)basis * (double)stacks)); } private static float GearPower(float basis, float stacks) { return LinearCooldown(basis, stacks); } private static float GesturePower(float basis, float exponent) { if (!Active) { return Mathf.Pow(basis, exponent); } return 2f / (Math.Max(0f, exponent) + 2f); } private static float LoopFactor(float basis, int stacks) { if (!Active) { return basis; } return LinearCooldown(basis, stacks); } private static int LoopBound(int count) { if (!Active) { return count; } if (count <= 0) { return 0; } return 1; } private static float Unclamp(float original, float raw) { if (!Active || float.IsNaN(raw) || float.IsInfinity(raw)) { return original; } return Math.Max(0f, raw); } private static int Cap(int cap) { if (!Active) { return cap; } return int.MaxValue; } private static float FlatPlate(float original, float raw) { if (!Active) { return original; } return Math.Max(0f, raw); } private static float RawChance(float percent) { if (!Active) { return Util.ConvertAmplificationPercentageIntoReductionPercentage(percent); } return percent; } private static float StunChance(float percent, DamageReport report) { if (!Active) { return Util.ConvertAmplificationPercentageIntoReductionPercentage(percent); } if (report != null && Object.op_Implicit((Object)(object)report.attackerMaster) && Object.op_Implicit((Object)(object)report.attackerMaster.inventory) && Object.op_Implicit((Object)(object)report.victim)) { int itemCountEffective = report.attackerMaster.inventory.GetItemCountEffective(Items.VileCenser); if (itemCountEffective > 1) { percent += 25f * (float)(itemCountEffective - 1) * (1f - Mathf.Clamp01(report.victim.combinedHealthFraction)) * report.damageInfo.procCoefficient; } } return percent; } private static float StunDuration(float duration, DamageReport report) { if (!Active || report == null || !Object.op_Implicit((Object)(object)report.attackerMaster) || !Object.op_Implicit((Object)(object)report.attackerMaster.inventory)) { return duration; } Inventory inventory = report.attackerMaster.inventory; float num = 5f * (float)inventory.GetItemCountEffective(Items.StunChanceOnHit); if (Object.op_Implicit((Object)(object)report.victim)) { num += 25f * (float)inventory.GetItemCountEffective(Items.VileCenser) * (1f - Mathf.Clamp01(report.victim.combinedHealthFraction)); } num *= report.damageInfo.procCoefficient; return duration * (float)NativeProcOverflow.ActivationCount(nativeResult: true, num, report.attackerMaster); } private static float TitanPower(float basis, float exponent) { if (!Active || exponent != 0.5f) { return Mathf.Pow(basis, exponent); } return basis; } private static int ConsumeOne(int original) { if (!Active) { return original; } return 1; } private static float MedkitFlat(float original, CharacterBody body) { if (!Active || !Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory)) { return original; } return original * (float)Math.Max(1, body.inventory.GetItemCountEffective(Items.Medkit)); } private static uint StackCap(uint original) { if (!Active) { return original; } return uint.MaxValue; } private static float BondFactor(float original, CharacterMaster master) { if (!Active || !Object.op_Implicit((Object)(object)master) || !Object.op_Implicit((Object)(object)master.inventory) || master.inventory.GetItemCountEffective(Items.OnLevelUpFreeUnlock) <= 0) { return original; } return 0.12f * (float)master.inventory.GetItemCountEffective(Items.OnLevelUpFreeUnlock); } internal static ulong BondExperience(double value) { if (!Active) { return (ulong)value; } if (double.IsNaN(value) || value <= 0.0) { return 0uL; } if (!(value >= 1.8446744073709552E+19)) { return (ulong)value; } return ulong.MaxValue; } } internal static class DeathMarkRule { private sealed class AppliedMark : MonoBehaviour { internal int Stacks; } [HarmonyPatch(typeof(GlobalEventManager), "ProcDeathMark")] private static class Applied { private static void Prefix(CharacterBody victimBody, out bool __state) { __state = Object.op_Implicit((Object)(object)victimBody) && victimBody.HasBuff(Buffs.DeathMark); } private static void Postfix(CharacterBody victimBody, CharacterMaster attackerMaster, bool __state) { if (DifficultyManager.Server && Rules.Enabled(Module.Items) && !__state && Object.op_Implicit((Object)(object)victimBody) && Object.op_Implicit((Object)(object)attackerMaster) && Object.op_Implicit((Object)(object)attackerMaster.inventory) && victimBody.HasBuff(Buffs.DeathMark)) { AppliedMark appliedMark = ((Component)victimBody).GetComponent<AppliedMark>(); if (!Object.op_Implicit((Object)(object)appliedMark)) { appliedMark = ((Component)victimBody).gameObject.AddComponent<AppliedMark>(); } appliedMark.Stacks = attackerMaster.inventory.GetItemCountEffective(Items.DeathMark); } } } [HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")] private static class Damage { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { bool mark = false; int found = 0; foreach (CodeInstruction code in input) { FieldInfo field = code.operand as FieldInfo; if (field != null && field.DeclaringType == typeof(Buffs) && field.Name == "DeathMark") { mark = true; } yield return code; if (mark && code.opcode == OpCodes.Ldc_R4 && (float)code.operand == 1.5f) { yield return new CodeInstruction(OpCodes.Ldarg_0, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DeathMarkRule), "Factor", (Type[])null, (Type[])null)); mark = false; found++; } } if (found != 1) { throw new InvalidOperationException("Death Mark damage anchor changed: " + found); } } } internal static float Factor(float original, HealthComponent target) { if (!DifficultyManager.Server || !Rules.Enabled(Module.Items) || !Object.op_Implicit((Object)(object)target)) { return original; } AppliedMark component = ((Component)target).GetComponent<AppliedMark>(); return original + 0.5f * (float)Math.Max(0, Object.op_Implicit((Object)(object)component) ? (component.Stacks - 1) : 0); } } internal static class DeferredEffects { internal delegate void Effect(object[] args, object[] locals); private sealed class Job { internal int Remaining; internal Effect Action; internal object[] Args; internal object[] Locals; internal DamageInfo Info; internal CharacterBody Attacker; internal int Stage; internal bool World; } private static readonly List<Effect> Actions = new List<Effect>(); private static readonly Queue<Job> Jobs = new Queue<Job>(); private static int frame = -1; private static int spent; internal static long Pending; private static int Budget => NoLimitsPlugin.Settings.ExtraProcBudgetPerFrame.Value; private static void NewFrame() { if (frame != Time.frameCount) { frame = Time.frameCount; spent = 0; } } internal static int Inline(int count) { NewFrame(); int num = Math.Min(Math.Max(0, count - 1), Math.Max(0, Budget - spent)); spent += num; if (count <= 0) { return 0; } return num + 1; } internal static void Enqueue(int id, int remaining, object[] args, object[] locals) { if (remaining > 0) { DamageInfo val = args.OfType<DamageInfo>().FirstOrDefault(); DamageReport val2 = args.OfType<DamageReport>().FirstOrDefault(); if (val == null && val2 != null) { val = val2.damageInfo; } CharacterBody attacker = ((val != null && Object.op_Implicit((Object)(object)val.attacker)) ? val.attacker.GetComponent<CharacterBody>() : null); Jobs.Enqueue(new Job { Action = Actions[id], Remaining = remaining, Args = args, Locals = locals, Info = val, Attacker = attacker, Stage = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.stageClearCount : 0) }); Pending += remaining; } } internal static void Schedule(Effect action, int count, object[] args, DamageInfo info) { if (count > 0 && info != null && Object.op_Implicit((Object)(object)info.attacker)) { Jobs.Enqueue(new Job { Action = action, Remaining = count, Args = args, Locals = new object[0], Info = info, Attacker = info.attacker.GetComponent<CharacterBody>(), Stage = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.stageClearCount : 0) }); Pending += count; } } internal static void ScheduleWorld(Effect action, int count, object[] args) { if (count > 0 && Object.op_Implicit((Object)(object)Run.instance)) { Jobs.Enqueue(new Job { Action = action, Remaining = count, Args = args, Locals = new object[0], Stage = Run.instance.stageClearCount, World = true }); Pending += count; } } internal static void Tick() { if (!DifficultyManager.Server || !Rules.Enabled(Module.Items)) { Clear(); return; } NewFrame(); while (Jobs.Count > 0 && spent < Budget) { Job job = Jobs.Dequeue(); if ((!job.World && !Object.op_Implicit((Object)(object)job.Attacker)) || !Object.op_Implicit((Object)(object)Run.instance) || job.Stage != Run.instance.stageClearCount) { Pending -= job.Remaining; continue; } spent++; job.Remaining--; Pending--; NativeProcOverflow.Frame frame = NativeProcOverflow.EnterDeferred(job.Info); try { job.Action(job.Args, job.Locals); } catch (Exception ex) { NoLimitsPlugin.Log.LogError((object)("Deferred native effect failed; remaining branch cancelled: " + ex)); Pending -= job.Remaining; job.Remaining = 0; } finally { NativeProcOverflow.ExitDeferred(frame); } if (job.Remaining > 0) { Jobs.Enqueue(job); } } } internal static void Clear() { Jobs.Clear(); Pending = 0L; } private static int Argument(CodeInstruction c) { if (c.opcode == OpCodes.Ldarg_0) { return 0; } if (c.opcode == OpCodes.Ldarg_1) { return 1; } if (c.opcode == OpCodes.Ldarg_2) { return 2; } if (c.opcode == OpCodes.Ldarg_3) { return 3; } if (c.opcode != OpCodes.Ldarg && c.opcode != OpCodes.Ldarg_S && c.opcode != OpCodes.Ldarga && c.opcode != OpCodes.Ldarga_S && c.opcode != OpCodes.Starg && c.opcode != OpCodes.Starg_S) { return -1; } if (c.operand is ParameterInfo { Position: var position } parameterInfo) { return position + ((!((MethodBase)parameterInfo.Member).IsStatic) ? 1 : 0); } return Convert.ToInt32(c.operand); } private static int Local(CodeInstruction c) { int num = AffineItemRules.LocalIndex(c, store: false); if (num >= 0) { return num; } num = AffineItemRules.LocalIndex(c, store: true); if (num >= 0) { return num; } if (c.opcode != OpCodes.Ldloca && c.opcode != OpCodes.Ldloca_S) { return -1; } if (c.operand is LocalBuilder localBuilder) { return localBuilder.LocalIndex; } if (c.operand is LocalVariableInfo localVariableInfo) { return localVariableInfo.LocalIndex; } return Convert.ToInt32(c.operand); } internal static Type[] LocalTypes(MethodBase method, List<CodeInstruction> codes) { Dictionary<int, Type> dictionary = method.GetMethodBody().LocalVariables.ToDictionary((LocalVariableInfo v) => v.LocalIndex, (LocalVariableInfo v) => v.LocalType); foreach (CodeInstruction code in codes) { if (code.operand is LocalBuilder localBuilder) { dictionary[localBuilder.LocalIndex] = localBuilder.LocalType; } } int num = ((dictionary.Count == 0) ? (-1) : dictionary.Keys.Max()); Type[] array = new Type[num + 1]; for (int num2 = 0; num2 < array.Length; num2++) { array[num2] = (dictionary.ContainsKey(num2) ? dictionary[num2] : typeof(object)); } if (array.Any((Type t) => t.IsByRef || t.IsPointer || t == typeof(TypedReference))) { throw new InvalidOperationException("Unboxable proc local in " + method.Name); } return array; } internal static Type[] ArgumentTypes(MethodBase method) { List<Type> list = new List<Type>(); if (!method.IsStatic) { list.Add(method.DeclaringType); } list.AddRange(from p in method.GetParameters() select p.ParameterType); return list.ToArray(); } internal static int Compile(MethodBase method, List<CodeInstruction> codes, int start, int end, Type[] types) { DynamicMethod dynamicMethod = new DynamicMethod("NoLimitsDeferred_" + method.Name + "_" + Actions.Count, typeof(void), new Type[2] { typeof(object[]), typeof(object[]) }, typeof(DeferredEffects).Module, skipVisibility: true); ILGenerator il = dynamicMethod.GetILGenerator(); LocalBuilder[] array = types.Select((Type t) => il.DeclareLocal(t)).ToArray(); Type[] array2 = ArgumentTypes(method); LocalBuilder[] array3 = array2.Select((Type t) => il.DeclareLocal(t)).ToArray(); for (int num = 0; num < array.Length; num++) { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldc_I4, num); il.Emit(OpCodes.Ldelem_Ref); il.Emit(OpCodes.Unbox_Any, types[num]); il.Emit(OpCodes.Stloc, array[num]); } for (int num2 = 0; num2 < array3.Length; num2++) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, num2); il.Emit(OpCodes.Ldelem_Ref); il.Emit(OpCodes.Unbox_Any, array2[num2]); il.Emit(OpCodes.Stloc, array3[num2]); } Label exit = il.DefineLabel(); Dictionary<Label, Label> labels = new Dictionary<Label, Label>(); for (int num3 = start; num3 < end; num3++) { foreach (Label label in codes[num3].labels) { if (!labels.ContainsKey(label)) { labels[label] = il.DefineLabel(); } } } for (int num4 = start; num4 < end; num4++) { CodeInstruction val = codes[num4]; foreach (Label label2 in val.labels) { il.MarkLabel(labels[label2]); } if (val.blocks.Count > 0) { throw new InvalidOperationException("Exception region inside deferred effect " + method.Name); } int num5 = Argument(val); int num6 = Local(val); if (num5 >= 0) { il.Emit((val.opcode == OpCodes.Ldarga || val.opcode == OpCodes.Ldarga_S) ? OpCodes.Ldloca : ((val.opcode == OpCodes.Starg || val.opcode == OpCodes.Starg_S) ? OpCodes.Stloc : OpCodes.Ldloc), array3[num5]); continue; } if (num6 >= 0) { il.Emit((val.opcode == OpCodes.Ldloca || val.opcode == OpCodes.Ldloca_S) ? OpCodes.Ldloca : ((AffineItemRules.LocalIndex(val, store: true) >= 0) ? OpCodes.Stloc : OpCodes.Ldloc), array[num6]); continue; } if (val.opcode == OpCodes.Ret) { il.Emit(OpCodes.Br, exit); continue; } object operand = val.operand; OpCode opcode = val.opcode; if (operand is Label key) { il.Emit(Long(opcode), labels.ContainsKey(key) ? labels[key] : exit); continue; } if (operand is Label[]) { il.Emit(opcode, ((Label[])operand).Select((Label l) => (!labels.ContainsKey(l)) ? exit : labels[l]).ToArray()); continue; } if (operand == null) { il.Emit(opcode); continue; } if (operand is MethodInfo) { il.Emit(opcode, (MethodInfo)operand); continue; } if (operand is ConstructorInfo) { il.Emit(opcode, (ConstructorInfo)operand); continue; } if (operand is FieldInfo) { il.Emit(opcode, (FieldInfo)operand); continue; } if (operand is Type) { il.Emit(opcode, (Type)operand); continue; } if (operand is string) { il.Emit(opcode, (string)operand); continue; } if (operand is float) { il.Emit(opcode, (float)operand); continue; } if (operand is double) { il.Emit(opcode, (double)operand); continue; } if (operand is long) { il.Emit(opcode, (long)operand); continue; } if (operand is sbyte) { il.Emit(opcode, (sbyte)operand); continue; } if (operand is byte) { il.Emit(opcode, (byte)operand); continue; } if (operand is short) { il.Emit(opcode, (short)operand); continue; } if (operand is int) { il.Emit(opcode, (int)operand); continue; } throw new InvalidOperationException(string.Concat("Unsupported effect operand ", operand.GetType(), " at ", method.Name)); } il.MarkLabel(exit); for (int num7 = 0; num7 < array.Length; num7++) { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldc_I4, num7); il.Emit(OpCodes.Ldloc, array[num7]); if (types[num7].IsValueType) { il.Emit(OpCodes.Box, types[num7]); } il.Emit(OpCodes.Stelem_Ref); } il.Emit(OpCodes.Ret); Effect item = (Effect)dynamicMethod.CreateDelegate(typeof(Effect)); int count = Actions.Count; Actions.Add(item); return count; } internal static OpCode Long(OpCode op) { if (!op.Name.EndsWith(".s", StringComparison.Ordinal)) { return op; } string b = op.Name.Substring(0, op.Name.Length - 2).Replace('.', '_'); FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (string.Equals(fieldInfo.Name, b, StringComparison.OrdinalIgnoreCase)) { return (OpCode)fieldInfo.GetValue(null); } } return op; } internal static IEnumerable<CodeInstruction> Snapshot(Type[] args, Type[] locals) { yield return new CodeInstruction(OpCodes.Ldc_I4, (object)args.Length); yield return new CodeInstruction(OpCodes.Newarr, (object)typeof(object)); for (int i = 0; i < args.Length; i++) { yield return new CodeInstruction(OpCodes.Dup, (object)null); yield return new CodeInstruction(OpCodes.Ldc_I4, (object)i); yield return new CodeInstruction(OpCodes.Ldarg, (object)(short)i); if (args[i].IsValueType) { yield return new CodeInstruction(OpCodes.Box, (object)args[i]); } yield return new CodeInstruction(OpCodes.Stelem_Ref, (object)null); } yield return new CodeInstruction(OpCodes.Ldc_I4, (object)locals.Length); yield return new CodeInstruction(OpCodes.Newarr, (object)typeof(object)); for (int j = 0; j < locals.Length; j++) { yield return new CodeInstruction(OpCodes.Dup, (object)null); yield return new CodeInstruction(OpCodes.Ldc_I4, (object)j); yield return new CodeInstruction(OpCodes.Ldloc, (object)(short)j); if (locals[j].IsValueType) { yield return new CodeInstruction(OpCodes.Box, (object)locals[j]); } yield return new CodeInstruction(OpCodes.Stelem_Ref, (object)null); } } } internal static class ExecutionOverflowRules { private sealed class Frame { internal Frame Previous; internal int Lens; internal bool Used; } private sealed class Work { internal Vector3 Position; internal GameObject Attacker; internal bool EliteOnly; } [HarmonyPatch(typeof(CharacterBody), "get_executeEliteHealthFraction")] private static class Guillotine { private static void Postfix(CharacterBody __instance, ref float __result) { if (DifficultyManager.Active && Rules.Enabled(Module.Items) && Object.op_Implicit((Object)(object)__instance.inventory)) { float num = 13f * (float)__instance.inventory.GetItemCountEffective(Items.ExecuteLowHealthElite); __result += num / 100f - Util.ConvertAmplificationPercentageIntoReductionPercentage(num) / 100f; } } } [HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")] private static class Lens { private static void Prefix(out Frame __state) { __state = new Frame { Previous = current }; current = __state; } private static Exception Finalizer(Exception __exception, Frame __state) { if (__state != null) { current = __state.Previous; } return __exception; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input, ILGenerator generator) { bool lens = false; int found = 0; foreach (CodeInstruction code in input) { FieldInfo field = code.operand as FieldInfo; if (field != null && field.DeclaringType == typeof(Items) && field.Name == "CritGlassesVoid") { lens = true; } MethodInfo call = code.operand as MethodInfo; if (lens && call != null && call.Name.Contains("g__LocalCheckRoll")) { LocalBuilder[] arguments = (from p in call.GetParameters() select generator.DeclareLocal(p.ParameterType)).ToArray(); for (int i = arguments.Length - 1; i >= 0; i--) { yield return new CodeInstruction(OpCodes.Stloc, (object)arguments[i]); } for (int i2 = 0; i2 < arguments.Length; i2++) { yield return new CodeInstruction(OpCodes.Ldloc, (object)arguments[i2]); } yield return code; yield return new CodeInstruction(OpCodes.Ldloc, (object)arguments[0]); yield return new CodeInstruction(OpCodes.Ldloc, (object)arguments[1]); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ExecutionOverflowRules), "LensRoll", (Type[])null, (Type[])null)); lens = false; found++; } else { yield return code; } } if (found != 1) { throw new InvalidOperationException("Lost Seer roll anchor changed: " + found); } } } [ThreadStatic] private static Frame current; [ThreadStatic] private static bool executing; internal static int Completed; private static bool Active { get { if (DifficultyManager.Server) { return Rules.Enabled(Module.Items); } return false; } } internal static void Install() { GlobalEventManager.onServerCharacterExecuted += Executed; } internal static void Uninstall() { GlobalEventManager.onServerCharacterExecuted -= Executed; } private static bool LensRoll(bool original, float chance, CharacterMaster master) { if (current != null && Active && !executing) { current.Lens = Math.Max(0, NativeProcOverflow.ActivationCount(original, chance, master) - 1); } return original; } private static void Executed(DamageReport report, float lost) { //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if (!Active || executing || current == null || current.Used || report == null || !Object.op_Implicit((Object)(object)report.attackerBody) || !Object.op_Implicit((Object)(object)report.attackerBody.inventory) || !Object.op_Implicit((Object)(object)report.victimBody)) { return; } current.Used = true; int num = current.Lens; bool eliteOnly = false; if (num == 0 && report.victimBody.isElite) { int itemCountEffective = report.attackerBody.inventory.GetItemCountEffective(Items.ExecuteLowHealthElite); if (itemCountEffective > 0) { num = Math.Max(0, NativeProcOverflow.ActivationCount(nativeResult: true, 13f * (float)itemCountEffective, report.attackerMaster) - 1); eliteOnly = true; } } if (num > 0) { DeferredEffects.Schedule(Execute, num, new object[1] { new Work { Position = report.victimBody.corePosition, Attacker = ((Component)report.attackerBody).gameObject, EliteOnly = eliteOnly } }, report.damageInfo); } } private static bool Story(CharacterBody body) { string name = ((Object)body).name; if (!name.StartsWith("Brother", StringComparison.Ordinal) && !name.StartsWith("VoidRaidCrab", StringComparison.Ordinal) && !name.StartsWith("FalseSonBoss", StringComparison.Ordinal) && !name.StartsWith("Providence", StringComparison.Ordinal) && !name.StartsWith("SolusHeart", StringComparison.Ordinal) && !name.StartsWith("SolusWing", StringComparison.Ordinal)) { return name.StartsWith("ScavLunar", StringComparison.Ordinal); } return true; } private static void Execute(object[] args, object[] locals) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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: Expected O, but got Unknown //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Invalid comparison between Unknown and I4 //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) Work work = (Work)args[0]; CharacterBody val = (Object.op_Implicit((Object)(object)work.Attacker) ? work.Attacker.GetComponent<CharacterBody>() : null); if (!Object.op_Implicit((Object)(object)val)) { return; } CharacterBody val2 = null; float value = NoLimitsPlugin.Settings.ExecutionOverflowRadius.Value; value *= value; TeamMask enemyTeams = TeamMask.GetEnemyTeams(val.teamComponent.teamIndex); foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) { if (Object.op_Implicit((Object)(object)readOnlyInstances) && Object.op_Implicit((Object)(object)readOnlyInstances.healthComponent) && readOnlyInstances.healthComponent.alive && !readOnlyInstances.healthComponent.godMode && Object.op_Implicit((Object)(object)readOnlyInstances.teamComponent) && ((TeamMask)(ref enemyTeams)).HasTeam(readOnlyInstances.teamComponent.teamIndex) && (int)readOnlyInstances.teamComponent.teamIndex != 0 && (int)readOnlyInstances.teamComponent.teamIndex != 1 && !Story(readOnlyInstances) && (readOnlyInstances.bodyFlags & 0x810) == 0 && !(work.EliteOnly ? (!readOnlyInstances.isElite) : readOnlyInstances.isBoss)) { Vector3 val4 = readOnlyInstances.corePosition - work.Position; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (!(sqrMagnitude >= value)) { value = sqrMagnitude; val2 = readOnlyInstances; } } } if (!Object.op_Implicit((Object)(object)val2)) { return; } executing = true; try { HealthComponent healthComponent = val2.healthComponent; DamageInfo val5 = new DamageInfo(); val5.attacker = work.Attacker; val5.damage = 1f; val5.procCoefficient = 0f; val5.procChainMask = NativeProcOverflow.CurrentInfo.procChainMask; val5.damageType = DamageTypeCombo.op_Implicit((DamageType)327746); val5.position = val2.corePosition; healthComponent.TakeDamage(val5); if (!val2.healthComponent.alive) { Completed++; } } finally { executing = false; } } } internal static class ItemStackingManager { [HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")] private static class DamageRules { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { int crit = 0; int bear = 0; bool voidBear = false; MethodInfo pow = AccessTools.Method(typeof(Mathf), "Pow", new Type[2] { typeof(float), typeof(float) }, (Type[])null); MethodInfo critGetter = AccessTools.PropertyGetter(typeof(CharacterBody), "critMultiplier"); foreach (CodeInstruction code in input) { FieldInfo field = code.operand as FieldInfo; if (field != null && field.DeclaringType == typeof(Items) && field.Name == "BearVoid") { voidBear = true; } if (voidBear && CodeInstructionExtensions.Calls(code, pow)) { code.opcode = OpCodes.Call; code.operand = AccessTools.Method(typeof(ItemStackingManager), "VoidBearPower", (Type[])null, (Type[])null); bear++; if (bear == 2) { voidBear = false; } } yield return code; if (CodeInstructionExtensions.Calls(code, critGetter)) { yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null); yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(ItemStackingManager), "ApplyCritOverflow", (Type[])null, (Type[])null)); crit++; } } if (crit != 1 || bear != 2) { throw new InvalidOperationException("Item IL changed: crit=" + crit + " voidBear=" + bear); } } } internal static float OverflowCritMultiplier(CharacterBody attacker) { return AdjustCrit(attacker.critMultiplier, attacker); } internal static float AdjustCrit(float original, CharacterBody attacker) { if (!DifficultyManager.Server || !Rules.Enabled(Module.Items) || attacker.crit <= 100f) { return original; } double num = ((double)attacker.crit - 100.0) / 100.0; double num2 = Math.Floor(num); if (Util.CheckRoll((float)((num - num2) * 100.0), attacker.master)) { num2 += 1.0; } double val = (double)original + num2 * (double)(original - 1f); return (float)Math.Min(3.4028234663852886E+38, val); } internal static float ApplyCritOverflow(float original, DamageInfo info) { CharacterBody val = ((info != null && Object.op_Implicit((Object)(object)info.attacker)) ? info.attacker.GetComponent<CharacterBody>() : null); if (!Object.op_Implicit((Object)(object)val)) { return original; } return AdjustCrit(original, val); } internal static float VoidBearPower(float basis, float stacks) { if (!DifficultyManager.Server || !Rules.Enabled(Module.Items)) { return Mathf.Pow(basis, stacks); } return Mathf.Max(Time.fixedDeltaTime, 13.5f / Mathf.Max(1f, stacks)) / 15f; } } internal static class LevelScalingManager { [HarmonyPatch(typeof(TeamManager), "GetExperienceForLevel")] private static class ExperienceTable { private static bool Prefix(uint __0, ref ulong __result) { if (!Extended) { return true; } __result = Threshold(__0, XpMultiplier); return false; } } [HarmonyPatch(typeof(TeamManager), "FindLevelForExperience")] private static class Inverse { private static bool Prefix(ulong __0, ref uint __result) { if (!Extended) { return true; } __result = Level(__0, XpMultiplier); return false; } } [HarmonyPatch(typeof(TeamManager), "SetTeamExperience")] private static class RemoveHardCap { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { int count = 0; foreach (CodeInstruction code in input) { yield return code; if (CodeInstructionExtensions.LoadsField(code, AccessTools.Field(typeof(TeamManager), "hardExpCap"), false)) { count++; yield return new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(LevelScalingManager), "ExperienceCap", (Type[])null, (Type[])null)); } } if (count != 2) { throw new InvalidOperationException("TeamManager hardExpCap IL changed: " + count); } } } [HarmonyPatch(typeof(Run), "RecalculateDifficultyCoefficentInternal")] private static class Ambient { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> input) { bool cap = false; int count = 0; MethodInfo min = AccessTools.Method(typeof(Mathf), "Min", new Type[2] { typeof(float), typeof(float) }, (Type[])null); foreach (CodeInstruction code in input) { if (CodeInstructionExtensions.LoadsField(code, AccessTools.Field(typeof(Run), "ambientLevelCap"), false)) { cap = true; } if (cap && CodeInstructionExtensions.Calls(code, min)) { code.opcode = OpCodes.Call; code.operand = AccessTools.Method(typeof(LevelScalingManager), "AmbientClamp", (Type[])null, (Type[])null); cap = false; count++; } yield return code; } if (count != 1) { throw new InvalidOperationException("Run ambient clamp IL changed: " + count); } } } private static bool Extended { get { if (DifficultyManager.Active && Rules.Enabled(Module.Levels)) { if (!SettingsSnapshot.Received) { return NoLimitsPlugin.Settings.RemovePlayerLevelCap.Value; } return SettingsSnapshot.RemovePlayerCap; } return false; } } private static float XpMultiplier { get { if (!SettingsSnapshot.Received) { return NoLimitsPlugin.Settings.PlayerXpRequirementMultiplier.Value; } return SettingsSnapshot.Xp; } } internal static ulong Threshold(uint level, float multiplier) { decimal num = ((level == 0) ? 0m : ((decimal)level - 1m)); decimal num2 = decimal.Ceiling((decimal)multiplier * (10m * num * num + 10m * num)); if (!(num2 >= 18446744073709551615m)) { return (ulong)num2; } return ulong.MaxValue; } internal static uint Level(ulong xp, float multiplier) { uint num = 1u; uint num2 = 4294967294u; while (num < num2) { uint num3 = num + (uint)(int)((ulong)((long)num2 - (long)num + 1) / 2uL); ulong num4 = Threshold(num3, multiplier); if (num4 < ulong.MaxValue && num4 <= xp) { num = num3; } else { num2 = num3 - 1; } } return num; } internal static ulong ExperienceCap(ulong original) { if (!Extended) { return original; } return ulong.MaxValue; } internal static float AmbientClamp(float value, float cap) { if (!DifficultyManager.Active || !Rules.Enabled(Module.Levels)) { return Mathf.Min(value, cap); } return ScaleAmbientGrowth(value, cap, SettingsSnapshot.Received ? SettingsSnapshot.Enemy : NoLimitsPlugin.Settings.EnemyLevelScalingMultiplier.Value, SettingsSnapshot.Received ? SettingsSnapshot.RemoveEnemyCap : NoLimitsPlugin.Settings.RemoveEnemyLevelCap.Value); } internal static float ScaleAmbientGrowth(float value, float cap, float multiplier, bool removeCap) { double num = 1.0 + ((double)value - 1.0) * (double)multiplier; double val = (removeCap ? 2147483391.0 : ((double)cap)); if (double.IsNaN(num)) { num = 1.0; } return (float)Math.Max(1.0, Math.Min(val, num)); } } internal static class LootOverflowRules { private sealed class ShrineFrame { internal ShrineFrame Previous; internal UniquePickup Pickup; } private sealed class ShrineWork { internal PickupDropTable Table; internal Xoroshiro128Plus Rng; internal Vector3 Position; internal Vector3 Velocity; internal UniquePickup Original; } private sealed class ExtraLunarDroplet : MonoBehaviour { } [HarmonyPatch(typeof(ShrineChanceBehavior), "AddShrineStack")] private static class ChanceDoll { private static void Prefix(out ShrineFrame __state) { __state = new ShrineFrame { Previous = shrine }; shrine = __state; } private static void Postfix(ShrineChanceBehavior __instance, Interactor __0, ShrineFrame __state) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_010a: 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) if (!Active || !Object.op_Implicit((Object)(object)__0) || __state.Pickup == UniquePickup.none || !Object.op_Implicit((Object)(object)__instance.chanceDollDropTable) || !(bool)AccessTools.Field(typeof(ShrineChanceBehavior), "chanceDollWin").GetValue(__instance)) { return; } CharacterBody component = ((Component)__0).GetComponent<CharacterBody>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.inventory)) { int num = NativeProcOverflow.ActivationCount(nativeResult: true, 40f * (float)component.inventory.GetItemCountEffective(Items.ExtraShrineItem), component.master) - 1; if (num > 0) { DeferredEffects.ScheduleWorld(DollDrop, num, new object[1] { new ShrineWork { Table = __instance.chanceDollDropTable, Rng = new Xoroshiro128Plus(Run.instance.treasureRng.nextUlong), Position = __instance.dropletOrigin.position, Velocity = __instance.dropletOrigin.forward * 20f, Original = __state.Pickup } }); } } } private static Exception Finalizer(Exception __exception, ShrineFrame __state) { if (__state != null) { shrine = __state.Previous; } return __exception; } } [HarmonyPatch(typeof(PickupDropletController), "CreatePickupDroplet", new Type[] { typeof(CreatePickupInfo), typeof(Vector3), typeof(Vector3) })] private static class CaptureShrineDrop { private static void Prefix(CreatePickupInfo __0) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (shrine != null) { shrine.Pickup = ((CreatePickupInfo)(ref __0)).pickup; } } } [HarmonyPatch(typeof(GenericPickupController), "CreatePickup")] private static class Eulogy { private static void Postfix(CreatePickupInfo __0) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) if (!dropletScope) { QueueLunar(__0); } } } [HarmonyPatch(typeof(PickupDropletController), "OnEnable")] private static class TagExtra { private static void Postfix(PickupDropletController __instance) { if (lunarExtra && !Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ExtraLunarDroplet>())) { ((Component)__instance).gameObject.AddComponent<ExtraLunarDroplet>(); } } } [HarmonyPatch(typeof(PickupDropletController), "CreatePickup")] private static class LandingScope { private static void Prefix(PickupDropletController __instance, out byte __state) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) __state = (byte)((lunarExtra ? 1 : 0) | (dropletScope ? 2 : 0)); dropletScope = true; lunarExtra |= Object.op_Implicit((Object)(object)((Component)__instance).GetComponent<ExtraLunarDroplet>()); CreatePickupInfo info = (CreatePickupInfo)AccessTools.Field(typeof(PickupDropletController), "createPickupInfo").GetValue(__instance); info.position = ((Component)__instance).transform.position; QueueLunar(info); } private static Exception Finalizer(Exception __exception, byte __state) { lunarExtra = (__state & 1) != 0; dropletScope = (__state & 2) != 0; return __exception; } } [ThreadStatic] private static ShrineFrame shrine; [ThreadStatic] private static bool lunarExtra; [ThreadStatic] private static bool dropletScope; internal static int LunarExtras; internal static int DollExtras; internal static ItemIndex LastLunarExtra = (ItemIndex)(-1); private static bool Active { get { if (DifficultyManager.Server) { return Rules.Enabled(Module.Items); } return false; } } private static void DollDrop(object[] args, object[] locals) { //IL_0018: Unknown