using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("GuaranteedCosmeticCrate")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("GuaranteedCosmeticCrate")] [assembly: AssemblyTitle("GuaranteedCosmeticCrate")] [assembly: AssemblyVersion("1.0.0.0")] namespace GuaranteedCosmeticCrate; [BepInPlugin("nzoow.repo.guaranteedcosmeticcrate", "GuaranteedCosmeticCrate", "3.0.0")] [BepInProcess("REPO.exe")] public class GuaranteedCosmeticCratePlugin : BaseUnityPlugin { internal static GuaranteedCosmeticCratePlugin Instance; internal static ManualLogSource Log; private Harmony harmony; internal ConfigEntry cfgGuaranteedCrate; internal ConfigEntry cfgSpawnChanceMultiplier; internal ConfigEntry cfgRareMultiplier; internal ConfigEntry cfgUltraRareMultiplier; internal ConfigEntry cfgVerboseLogs; private MethodInfo spawnMethod; private void Awake() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; BindConfig(); harmony = new Harmony("nzoow.repo.guaranteedcosmeticcrate"); harmony.PatchAll(); Type type = AccessTools.TypeByName("ValuableDirector"); if (type != null) { spawnMethod = AccessTools.Method(type, "SpawnCosmeticWorldObject", (Type[])null, (Type[])null); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[GuaranteedCrate] Plugin loaded"); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } } private void BindConfig() { cfgGuaranteedCrate = ((BaseUnityPlugin)this).Config.Bind("General", "GuaranteedCrate", true, "Guarantee at least one cosmetic crate"); cfgSpawnChanceMultiplier = ((BaseUnityPlugin)this).Config.Bind("General", "SpawnChanceMultiplier", 1.5f, "Multiplier for vanilla cosmetic spawn chance"); cfgRareMultiplier = ((BaseUnityPlugin)this).Config.Bind("Rarity", "RareMultiplier", 4f, "Rare chance multiplier"); cfgUltraRareMultiplier = ((BaseUnityPlugin)this).Config.Bind("Rarity", "UltraRareMultiplier", 2f, "UltraRare chance multiplier"); cfgVerboseLogs = ((BaseUnityPlugin)this).Config.Bind("Debug", "VerboseLogs", true, "Enable detailed logs"); } internal void TryGuaranteeCrate(ValuableDirector director) { //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)director == (Object)null || spawnMethod == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GuaranteedCrate] Director or spawn method null"); return; } try { FieldInfo fieldInfo = AccessTools.Field(typeof(ValuableDirector), "cosmeticWorldObjectTargetAmount"); int num = ((fieldInfo != null) ? ((int)fieldInfo.GetValue(director)) : 0); if (num > 0) { if (cfgVerboseLogs.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[GuaranteedCrate] Vanilla already spawned crate(s): " + num)); } return; } if (!cfgGuaranteedCrate.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[GuaranteedCrate] Guaranteed crate disabled"); return; } ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GuaranteedCrate] No vanilla cosmetic crate detected."); ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GuaranteedCrate] Forcing cosmetic crate spawn..."); List list = Object.FindObjectsOfType(false).ToList(); List[] array = new List[7] { list.FindAll((ValuableVolume x) => (int)x.VolumeType == 0), list.FindAll((ValuableVolume x) => (int)x.VolumeType == 1), list.FindAll((ValuableVolume x) => (int)x.VolumeType == 2), list.FindAll((ValuableVolume x) => (int)x.VolumeType == 3), list.FindAll((ValuableVolume x) => (int)x.VolumeType == 4), list.FindAll((ValuableVolume x) => (int)x.VolumeType == 5), list.FindAll((ValuableVolume x) => (int)x.VolumeType == 6) }; List[] array2 = array; for (int i = 0; i < array2.Length; i++) { array2[i].Shuffle(); } int[] array3 = new int[7]; Rarity val = RollRarity(director); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[GuaranteedCrate] Selected rarity: " + ((object)(Rarity)(ref val)).ToString())); spawnMethod.Invoke(director, new object[3] { val, array3, array }); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[GuaranteedCrate] Cosmetic crate spawned successfully"); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[GuaranteedCrate] Force spawn failed:\n" + ex)); } } private Rarity RollRarity(ValuableDirector director) { //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected I4, but got Unknown //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) try { int num = director.CosmeticWorldObjectLevelLoopsGet(); float num2 = ((director.CosmeticWorldObjectLevelLoopsClampedGet() < num) ? 1f : ((float)(RunManager.instance.levelsCompleted % director.cosmeticWorldObjectsLevelLoop) / (float)director.cosmeticWorldObjectsLevelLoop)); float num3 = 0f; float num4 = 0f; float num5 = 0f; float num6 = 0f; foreach (CosmeticWorldObjectSetup cosmeticWorldObjectSetup in director.cosmeticWorldObjectSetups) { float num7 = Mathf.Max(0f, cosmeticWorldObjectSetup.chanceCurve.Evaluate(num2)); Rarity rarity = cosmeticWorldObjectSetup.rarity; switch ((int)rarity) { case 0: num3 += num7 * 0.3f; break; case 1: num4 += num7 * 0.5f; break; case 2: num5 += num7 * cfgRareMultiplier.Value; break; case 3: num6 += num7 * cfgUltraRareMultiplier.Value; break; } } float num8 = num3 + num4 + num5 + num6; if (num8 <= 0f) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[GuaranteedCrate] Invalid rarity total, fallback Common"); return (Rarity)0; } float num9 = Random.Range(0f, num8); if (num9 < num3) { return (Rarity)0; } num9 -= num3; if (num9 < num4) { return (Rarity)1; } num9 -= num4; if (num9 < num5) { return (Rarity)2; } return (Rarity)3; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[GuaranteedCrate] RollRarity failed:\n" + ex)); return (Rarity)0; } } } [HarmonyPatch(typeof(ValuableDirector), "SetupHost")] internal static class ValuableDirectorPatch { [CompilerGenerated] private sealed class d__0 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public IEnumerator __result; public ValuableDirector __instance; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_0045; case 1: <>1__state = -1; goto IL_0045; case 2: { <>1__state = -1; GuaranteedCosmeticCratePlugin.Instance.TryGuaranteeCrate(__instance); return false; } IL_0045: if (__result.MoveNext()) { <>2__current = __result.Current; <>1__state = 1; return true; } if ((Object)(object)GuaranteedCosmeticCratePlugin.Instance == (Object)null) { return false; } <>2__current = (object)new WaitForSeconds(0.25f); <>1__state = 2; return true; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(d__0))] private static IEnumerator Postfix(IEnumerator __result, ValuableDirector __instance) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__0(0) { __result = __result, __instance = __instance }; } } [HarmonyPatch(typeof(Random), "Range", new Type[] { typeof(int), typeof(int) })] internal static class CosmeticSpawnChancePatch { private static void Prefix(int minInclusive, ref int maxExclusive) { try { if (!((Object)(object)GuaranteedCosmeticCratePlugin.Instance == (Object)null)) { float value = GuaranteedCosmeticCratePlugin.Instance.cfgSpawnChanceMultiplier.Value; if (!(value <= 1f) && maxExclusive == 100) { maxExclusive = Mathf.Max(1, Mathf.RoundToInt((float)maxExclusive / value)); } } } catch { } } } internal static class ShuffleExt { internal static void Shuffle(this IList list) { for (int num = list.Count - 1; num > 0; num--) { int index = Random.Range(0, num + 1); T value = list[num]; list[num] = list[index]; list[index] = value; } } }