Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of RecipeRandomizer Il2cpp v1.1.0
RecipeRandomizer.dll
Decompiled 11 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using HarmonyLib; using Il2CppFishNet.Connection; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Effects; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.Persistence.Datas; using Il2CppScheduleOne.Persistence.ItemLoaders; using Il2CppScheduleOne.Persistence.Loaders; using Il2CppScheduleOne.Product; using Il2CppScheduleOne.StationFramework; using Il2CppScheduleOne.UI; using Il2CppSystem.Collections.Generic; using MelonLoader; using MelonLoader.Utils; using Newtonsoft.Json.Linq; using RecipeRandomizerNs; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(global::RecipeRandomizerNs.RecipeRandomizerNs), "RecipeRandomizer", "1.1.0", "xVilho", null)] [assembly: MelonColor(255, 180, 55, 255)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("RecipeRandomizer")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+327ef61a31176f5f06933c2cdef4fecb87553f89")] [assembly: AssemblyProduct("RecipeRandomizer")] [assembly: AssemblyTitle("RecipeRandomizer")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace RecipeRandomizerNs; public static class SaveHelper { internal static string LatestSaveFolder; internal static bool OverrideSeed = true; internal static int CustomSeed = 123456789; internal static List<string> CustomName1 = new List<string>(); internal static List<string> CustomName2 = new List<string>(); private static string ConfigJsonPath => Path.Combine(MelonEnvironment.ModsDirectory, "RecipeRandomizerConfig.json"); public static void LoadOrCreateConfig() { //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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_012c: Expected O, but got Unknown if (!File.Exists(ConfigJsonPath)) { JObject val = new JObject { ["_MaxSeedComment"] = JToken.op_Implicit($"Set seed between -{int.MaxValue} - {int.MaxValue}"), ["OverrideSeed"] = JToken.op_Implicit(true), ["CustomSeed"] = JToken.op_Implicit(int.MaxValue) }; JArray val2 = new JArray(); val2.Add(JToken.op_Implicit("Cosmic")); val2.Add(JToken.op_Implicit("Quantum")); val2.Add(JToken.op_Implicit("Giga")); val2.Add(JToken.op_Implicit("Turbo")); val["Name1"] = (JToken)val2; JArray val3 = new JArray(); val3.Add(JToken.op_Implicit("Crunch")); val3.Add(JToken.op_Implicit("Goblin")); val3.Add(JToken.op_Implicit("Pickle")); val3.Add(JToken.op_Implicit("Vortex")); val["Name2"] = (JToken)val3; JObject val4 = val; File.WriteAllText(ConfigJsonPath, ((object)val4).ToString()); RecipeRandomizerNs.Log("\ud83d\udee0\ufe0f Created default Config.json"); } JObject obj = JObject.Parse(File.ReadAllText(ConfigJsonPath)); JToken obj2 = obj["OverrideSeed"]; OverrideSeed = obj2 != null && Extensions.Value<bool>((IEnumerable<JToken>)obj2); JToken obj3 = obj["CustomSeed"]; CustomSeed = ((obj3 != null) ? Extensions.Value<int>((IEnumerable<JToken>)obj3) : 123456789); JToken obj4 = obj["Name1"]; CustomName1 = ((obj4 != null) ? obj4.ToObject<List<string>>() : null) ?? new List<string>(); JToken obj5 = obj["Name2"]; CustomName2 = ((obj5 != null) ? obj5.ToObject<List<string>>() : null) ?? new List<string>(); RecipeRandomizerNs.Logger.Msg($"✅ Loaded Config.json: OverrideSeed={OverrideSeed}, CustomSeed={CustomSeed}, Name1={CustomName1.Count}, Name2={CustomName2.Count}"); } public static int LoadSaveSeed() { try { if (OverrideSeed) { RecipeRandomizerNs.Log($"[SaveHelper] \ud83d\ude80 Using override seed {CustomSeed}"); return CustomSeed; } string text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData).Replace("Local", "LocalLow", StringComparison.OrdinalIgnoreCase), "TVGS", "Schedule I", "Saves"); if (!Directory.Exists(text)) { RecipeRandomizerNs.LogWarning("❌ Save root folder not found: " + text); return 0; } string[] directories = Directory.GetDirectories(text); if (directories.Length == 0) { RecipeRandomizerNs.LogWarning("❌ No SteamID folders found."); return 0; } DirectoryInfo directoryInfo = new DirectoryInfo(directories[0]); DirectoryInfo directoryInfo2 = null; DirectoryInfo[] directories2 = directoryInfo.GetDirectories("SaveGame_*"); foreach (DirectoryInfo directoryInfo3 in directories2) { if (directoryInfo2 == null || directoryInfo3.LastWriteTimeUtc > directoryInfo2.LastWriteTimeUtc) { directoryInfo2 = directoryInfo3; } } if (directoryInfo2 == null) { RecipeRandomizerNs.LogWarning("❌ No SaveGame_* directories inside: " + directoryInfo.FullName); return 0; } LatestSaveFolder = directoryInfo2.FullName; RecipeRandomizerNs.Log("\ud83d\udcc2 Found latest save folder: " + Path.GetFileName(LatestSaveFolder)); string path = Path.Combine(LatestSaveFolder, "Game.json"); if (!File.Exists(path)) { RecipeRandomizerNs.LogWarning("❌ Game.json not found in save"); return 0; } JToken obj = JObject.Parse(File.ReadAllText(path))["Seed"]; int num = ((obj != null) ? Extensions.Value<int>((IEnumerable<JToken>)obj) : 0); RecipeRandomizerNs.Log($"\ud83d\udce6 Loaded seed from Game.json: {num}"); return num; } catch (Exception ex) { RecipeRandomizerNs.LogError("❌ Exception during LoadSaveSeed: " + ex.Message); return 0; } } } public class RecipeRandomizerNs : MelonMod { [CompilerGenerated] private sealed class <StartupCoroutine>d__12 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <StartupCoroutine>d__12(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; if (Logger == null) { return false; } SaveSeed = SaveHelper.LoadSaveSeed(); Logger.Msg($"Save Seed loaded: {SaveSeed}"); Log("Waiting for ProductManager..."); break; case 1: <>1__state = -1; break; } if ((Object)(object)NetworkSingleton<ProductManager>.Instance == (Object)null) { <>2__current = null; <>1__state = 1; return true; } Log("ProductManager ready."); Il2CppArrayBase<Effect> obj = Resources.FindObjectsOfTypeAll<Effect>(); List<Effect> val = new List<Effect>(obj.Length); foreach (Effect item in obj) { val.Add(item); } CachedAllEffects = val; Log($"Cached {CachedAllEffects.Count} Effect effects."); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal static Instance Logger; private static readonly bool DebugLog; private static readonly bool DebugWarning; private static readonly bool DebugLogError; public static List<Effect> CachedAllEffects; public static int SaveSeed; private Harmony harmony; public static void Log(string msg) { if (DebugLog && Logger != null) { Logger.Msg(msg); } } public static void LogWarning(string msg) { if (DebugWarning && Logger != null) { Logger.Warning(msg); } } public static void LogError(string msg) { if (DebugLogError && Logger != null) { Logger.Error(msg); } } public override void OnInitializeMelon() { Logger = ((MelonBase)this).LoggerInstance; Log("Initialized."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown if (Logger == null) { return; } Log($"Scene loaded: {sceneName} ({buildIndex})"); if (sceneName == "Menu") { SaveHelper.LoadOrCreateConfig(); } if (sceneName == "Main") { Log("Main Scene loaded. Applying Harmony patches and starting randomization coroutine..."); try { harmony = new Harmony("recipe.randomizer.patch"); harmony.PatchAll(); Log("Harmony patches applied."); } catch (Exception value) { LogError($"Harmony patching failed: {value}"); } MelonCoroutines.Start(StartupCoroutine()); } } [IteratorStateMachine(typeof(<StartupCoroutine>d__12))] private static IEnumerator StartupCoroutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <StartupCoroutine>d__12(0); } } [HarmonyPatch(typeof(EffectMixCalculator), "MixProperties")] public static class EffectMixCalculator_Patch { private static readonly Dictionary<int, List<Effect>> _cache = new Dictionary<int, List<Effect>>(); public static void Postfix(List<Effect> existingProperties, Effect newProperty, EDrugType drugType, ref List<Effect> __result) { if (RecipeRandomizerNs.Logger == null || RecipeRandomizerNs.SaveSeed == 0) { return; } existingProperties = existingProperties ?? new List<Effect>(); __result = __result ?? new List<Effect>(); if ((Object)(object)NetworkSingleton<ProductManager>.Instance.GetRecipe(existingProperties, newProperty) != (Object)null) { return; } int num = RecipeRandomizerNs.SaveSeed; Enumerator<Effect> enumerator = existingProperties.GetEnumerator(); while (enumerator.MoveNext()) { Effect current = enumerator.Current; num ^= StableHash(((Object)current).name); } if ((Object)(object)newProperty != (Object)null) { num ^= StableHash(((Object)newProperty).name); } Random random = new Random(num); List<Effect> val = default(List<Effect>); if (_cache.TryGetValue(num, ref val)) { List<Effect> val2 = new List<Effect>(); enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { Effect current2 = enumerator.Current; val2.Add(current2); } __result = val2; return; } List<Effect> val3 = new List<Effect>(); List<Effect> val4 = new List<Effect>(); enumerator = RecipeRandomizerNs.CachedAllEffects.GetEnumerator(); while (enumerator.MoveNext()) { Effect current3 = enumerator.Current; val4.Add(current3); } enumerator = existingProperties.GetEnumerator(); while (enumerator.MoveNext()) { _ = enumerator.Current; if (val4.Count == 0) { break; } int num2 = random.Next(val4.Count); val3.Add(val4[num2]); val4.RemoveAt(num2); } if ((Object)(object)newProperty != (Object)null && !val3.Contains(newProperty) && val3.Count < 8) { val3.Add(newProperty); } List<Effect> val5 = new List<Effect>(); enumerator = val3.GetEnumerator(); while (enumerator.MoveNext()) { Effect current4 = enumerator.Current; val5.Add(current4); } _cache[num] = val5; __result = val3; } private static int StableHash(string s) { int num = -2128831035; byte[] bytes = Encoding.UTF8.GetBytes(s); foreach (byte b in bytes) { num = (num ^ b) * 16777619; } return num; } public static void ClearCache() { _cache.Clear(); } } [HarmonyPatch] public static class ProductManager_GetRecipe_Patch { private static MethodBase TargetMethod() { return typeof(ProductManager).GetMethod("GetRecipe", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(List<Effect>), typeof(Effect) }, null); } private static void Postfix(List<Effect> productProperties, Effect mixerProperty, ref StationRecipe __result) { if (RecipeRandomizerNs.Logger != null && (Object)(object)__result == (Object)null && productProperties != null) { RecipeRandomizerNs.Log($"No recipe found for {productProperties.Count} effects + {(Object.op_Implicit((Object)(object)mixerProperty) ? ((Object)mixerProperty).name : "null")}."); } } } [HarmonyPatch(typeof(NewMixScreen), "Awake")] public static class NewMixScreen_Awake_Patch { public static void Postfix(NewMixScreen __instance) { if ((Object)(object)__instance == (Object)null || RecipeRandomizerNs.Logger == null) { RecipeRandomizerNs.LogError("NewMixScreen instance is null in Awake Postfix."); return; } RecipeRandomizerNs.Log("Attempting to add custom names via NewMixScreen.Awake Postfix..."); try { List<string> name1Library = __instance.name1Library; if (name1Library != null && SaveHelper.CustomName1.Count > 0) { int num = 0; foreach (string item in SaveHelper.CustomName1) { if (!name1Library.Contains(item)) { name1Library.Add(item); num++; } } if (num > 0) { RecipeRandomizerNs.Log($"Added {num} custom names to name1Library."); } else { RecipeRandomizerNs.Log("No new custom names to add to name1Library. Skipping."); } } List<string> name2Library = __instance.name2Library; if (name2Library == null || SaveHelper.CustomName2.Count <= 0) { return; } int num2 = 0; foreach (string item2 in SaveHelper.CustomName2) { if (!name2Library.Contains(item2)) { name2Library.Add(item2); num2++; } } if (num2 > 0) { RecipeRandomizerNs.Log($"Added {num2} custom names to name2Library."); } else { RecipeRandomizerNs.Log("No new custom names to add to name2Library. Skipping."); } } catch (Exception ex) { RecipeRandomizerNs.LogError("Exception patching NewMixScreen.Awake: " + ex.Message); } } } [HarmonyPatch(typeof(NewMixScreen), "RandomizeButtonClicked")] public static class NewMixScreen_RandomizeButtonClicked_Patch { public static void Postfix(NewMixScreen __instance) { if (!((Object)(object)__instance == (Object)null)) { List<string> name1Library = __instance.name1Library; List<string> name2Library = __instance.name2Library; if (name1Library != null && name2Library != null && name1Library.Count != 0 && name2Library.Count != 0) { Random random = new Random(RecipeRandomizerNs.SaveSeed ^ DateTime.Now.Millisecond); string text = name1Library[random.Next(name1Library.Count)]; string text2 = name2Library[random.Next(name2Library.Count)]; __instance.nameInputField.text = text + " " + text2; } } } } [HarmonyPatch(typeof(NewMixScreen), "Open")] public static class NewMixScreen_Open_Patch { public static void Postfix(NewMixScreen __instance) { if (!((Object)(object)__instance == (Object)null)) { List<string> name1Library = __instance.name1Library; List<string> name2Library = __instance.name2Library; if (name1Library != null && name2Library != null && name1Library.Count != 0 && name2Library.Count != 0) { Random random = new Random(RecipeRandomizerNs.SaveSeed ^ DateTime.Now.Millisecond); string text = name1Library[random.Next(name1Library.Count)]; string text2 = name2Library[random.Next(name2Library.Count)]; __instance.nameInputField.text = text + " " + text2; } } } } public class CustomProductState { public float RandomPotency; public List<Effect> RandomizedEffects = new List<Effect>(); } public static class CustomProductManager { private static readonly Dictionary<string, CustomProductState> registry = new Dictionary<string, CustomProductState>(); public static void Register(string id, CustomProductState state) { if (!string.IsNullOrEmpty(id) && state != null) { registry[id] = state; } } public static bool TryGet(string id, out CustomProductState state) { return registry.TryGetValue(id, out state); } public static void Clear() { registry.Clear(); } } [HarmonyPatch] public static class ProductManager_CreateWeed_Patch { private static MethodBase TargetMethod() { return typeof(ProductManager).GetMethod("CreateWeed", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[6] { typeof(NetworkConnection), typeof(string), typeof(string), typeof(EDrugType), typeof(List<string>), typeof(WeedAppearanceSettings) }, null); } private static void Postfix(NetworkConnection conn, string name, string id, EDrugType type, List<string> properties, WeedAppearanceSettings appearance) { RecipeRandomizerNs.Log("CreateWeed called for product ID: " + id); if (CustomProductManager.TryGet(id, out var _)) { return; } if (RecipeRandomizerNs.CachedAllEffects == null || RecipeRandomizerNs.CachedAllEffects.Count == 0) { RecipeRandomizerNs.LogWarning("No effects cached"); return; } Random random = new Random(RecipeRandomizerNs.SaveSeed ^ StableHash(id)); List<Effect> randomizedEffects = new List<Effect>(); List<Effect> val = new List<Effect>(RecipeRandomizerNs.CachedAllEffects.Count); Enumerator<Effect> enumerator = RecipeRandomizerNs.CachedAllEffects.GetEnumerator(); while (enumerator.MoveNext()) { Effect current = enumerator.Current; val.Add(current); } float randomPotency = (float)(random.NextDouble() * 5.0 + 1.0); CustomProductManager.Register(id, new CustomProductState { RandomPotency = randomPotency, RandomizedEffects = randomizedEffects }); RecipeRandomizerNs.Log("Registered state for " + id); } private static int StableHash(string s) { int num = -2128831035; byte[] bytes = Encoding.UTF8.GetBytes(s); foreach (byte b in bytes) { num = (num ^ b) * 16777619; } return num; } } [HarmonyPatch] public static class ProductManager_CreateMeth_Patch { private static MethodBase TargetMethod() { return typeof(ProductManager).GetMethod("CreateMeth", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[6] { typeof(NetworkConnection), typeof(string), typeof(string), typeof(EDrugType), typeof(List<string>), typeof(MethAppearanceSettings) }, null); } private static void Postfix(NetworkConnection conn, string name, string id, EDrugType type, List<string> properties, MethAppearanceSettings appearance) { RecipeRandomizerNs.Log("\ud83d\udc8a CreateMeth called for product ID: " + id); if (CustomProductManager.TryGet(id, out var _)) { return; } if (RecipeRandomizerNs.CachedAllEffects == null || RecipeRandomizerNs.CachedAllEffects.Count == 0) { RecipeRandomizerNs.LogWarning("❌ No Effect effects cached!"); return; } Random random = new Random(RecipeRandomizerNs.SaveSeed ^ StableHash(id)); List<Effect> val = new List<Effect>(); List<Effect> val2 = new List<Effect>(RecipeRandomizerNs.CachedAllEffects.Count); Enumerator<Effect> enumerator = RecipeRandomizerNs.CachedAllEffects.GetEnumerator(); while (enumerator.MoveNext()) { Effect current = enumerator.Current; val2.Add(current); } for (int i = 0; i < properties.Count; i++) { if (val2.Count <= 0) { break; } int num = random.Next(val2.Count); val.Add(val2[num]); val2.RemoveAt(num); } float randomPotency = (float)(random.NextDouble() * 5.0 + 1.0); CustomProductManager.Register(id, new CustomProductState { RandomPotency = randomPotency, RandomizedEffects = val }); RecipeRandomizerNs.Log("\ud83d\udce6 Registered custom Meth state for " + id); } private static int StableHash(string s) { int num = -2128831035; byte[] bytes = Encoding.UTF8.GetBytes(s); foreach (byte b in bytes) { num = (num ^ b) * 16777619; } return num; } } [HarmonyPatch] public static class ProductManager_CreateCocaine_Patch { private static MethodBase TargetMethod() { return typeof(ProductManager).GetMethod("CreateCocaine", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[6] { typeof(NetworkConnection), typeof(string), typeof(string), typeof(EDrugType), typeof(List<string>), typeof(CocaineAppearanceSettings) }, null); } private static void Postfix(NetworkConnection conn, string name, string id, EDrugType type, List<string> properties, CocaineAppearanceSettings appearance) { RecipeRandomizerNs.Log("❄\ufe0f CreateCocaine called for product ID: " + id); if (CustomProductManager.TryGet(id, out var _)) { return; } if (RecipeRandomizerNs.CachedAllEffects == null || RecipeRandomizerNs.CachedAllEffects.Count == 0) { RecipeRandomizerNs.LogWarning("❌ No Effect effects cached!"); return; } Random random = new Random(RecipeRandomizerNs.SaveSeed ^ StableHash(id)); List<Effect> val = new List<Effect>(); List<Effect> val2 = new List<Effect>(RecipeRandomizerNs.CachedAllEffects.Count); Enumerator<Effect> enumerator = RecipeRandomizerNs.CachedAllEffects.GetEnumerator(); while (enumerator.MoveNext()) { Effect current = enumerator.Current; val2.Add(current); } for (int i = 0; i < properties.Count; i++) { if (val2.Count <= 0) { break; } int num = random.Next(val2.Count); val.Add(val2[num]); val2.RemoveAt(num); } float randomPotency = (float)(random.NextDouble() * 5.0 + 1.0); CustomProductManager.Register(id, new CustomProductState { RandomPotency = randomPotency, RandomizedEffects = val }); RecipeRandomizerNs.Log("\ud83d\udce6 Registered custom Cocaine state for " + id); } private static int StableHash(string s) { int num = -2128831035; byte[] bytes = Encoding.UTF8.GetBytes(s); foreach (byte b in bytes) { num = (num ^ b) * 16777619; } return num; } } [HarmonyPatch(typeof(ProductItemInstance), "GetItemData")] public static class ProductItemInstance_GetItemData_Patch { [HarmonyPatch(typeof(WeedLoader), "LoadItem")] public static class WeedLoader_LoadItem_Patch { public static void Postfix(ref ItemInstance __result) { ItemInstance obj = __result; WeedInstance val = (WeedInstance)(object)((obj is WeedInstance) ? obj : null); if (val == null || string.IsNullOrEmpty(((ItemInstance)val).ID)) { return; } Random random = new Random(RecipeRandomizerNs.SaveSeed ^ ((ItemInstance)val).ID.GetHashCode()); List<Effect> val2 = new List<Effect>(); List<Effect> val3 = new List<Effect>(RecipeRandomizerNs.CachedAllEffects.Count); Enumerator<Effect> enumerator = RecipeRandomizerNs.CachedAllEffects.GetEnumerator(); while (enumerator.MoveNext()) { Effect current = enumerator.Current; val3.Add(current); } for (int i = 0; i < 3; i++) { if (val3.Count <= 0) { break; } int num = random.Next(val3.Count); val2.Add(val3[num]); val3.RemoveAt(num); } float randomPotency = (float)(random.NextDouble() * 5.0 + 1.0); CustomProductManager.Register(((ItemInstance)val).ID, new CustomProductState { RandomPotency = randomPotency, RandomizedEffects = val2 }); RecipeRandomizerNs.Log("\ud83d\udce6 Registered custom data for Weed " + ((ItemInstance)val).ID); } } public static void Postfix(ProductItemInstance __instance, ref ItemData __result) { ItemData obj = __result; ProductItemData val = (ProductItemData)(object)((obj is ProductItemData) ? obj : null); if (val != null && CustomProductManager.TryGet(((ItemInstance)__instance).ID, out var state)) { ((ItemData)val).ID = RecipeUtils.AppendCustomSuffix(((ItemData)val).ID, state); RecipeRandomizerNs.Log("Appended custom suffix to ProductItemData ID: " + ((ItemData)val).ID); } } private static string AppendCustomSuffix(string originalID, CustomProductState state) { List<string> list = new List<string>(); Enumerator<Effect> enumerator = state.RandomizedEffects.GetEnumerator(); while (enumerator.MoveNext()) { Effect current = enumerator.Current; list.Add(((Object)current).name); } string value = string.Join("-", list); return $"{originalID}|RP:{state.RandomPotency:0.00}|FX:{value}"; } } public static class RecipeUtils { public static string AppendCustomSuffix(string originalID, CustomProductState state) { List<string> list = new List<string>(); Enumerator<Effect> enumerator = state.RandomizedEffects.GetEnumerator(); while (enumerator.MoveNext()) { Effect current = enumerator.Current; list.Add(((Object)current).name); } string value = string.Join("-", list); return $"{originalID}|RP:{state.RandomPotency:0.00}|FX:{value}"; } } [HarmonyPatch(typeof(WeedProductLoader), "Load")] public static class WeedProductLoader_Load_Patch { public static void Postfix() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown RecipeRandomizerNs.Log("Postfix: WeedProductLoader.Load invoked"); ProductManager instance = NetworkSingleton<ProductManager>.Instance; List<ProductDefinition> val = ((instance != null) ? instance.createdProducts : null); if (val == null) { RecipeRandomizerNs.LogError("createdProducts is null!"); return; } Enumerator<ProductDefinition> enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { ProductDefinition current = enumerator.Current; WeedDefinition val2 = (WeedDefinition)(object)((current is WeedDefinition) ? current : null); if (val2 != null && !CustomProductManager.TryGet(((ItemDefinition)val2).ID, out var _)) { WeedAppearanceSettings val3 = new WeedAppearanceSettings(Color32.op_Implicit(val2.MainMat.color), Color32.op_Implicit(val2.SecondaryMat.color), Color32.op_Implicit(val2.LeafMat.color), Color32.op_Implicit(val2.StemMat.color)); List<string> val4 = new List<string>(); Enumerator<Effect> enumerator2 = ((PropertyItemDefinition)val2).Properties.GetEnumerator(); while (enumerator2.MoveNext()) { Effect current2 = enumerator2.Current; val4.Add(current2.ID); } WeedDefinition val5 = Object.Instantiate<WeedDefinition>(NetworkSingleton<ProductManager>.Instance.DefaultWeed); ((Object)val5).name = ((ItemDefinition)val2).Name; ((ItemDefinition)val5).Name = ((ItemDefinition)val2).Name; ((ItemDefinition)val5).Description = string.Empty; ((ItemDefinition)val5).ID = ((ItemDefinition)val2).ID; List<EDrugType> val6 = new List<EDrugType>(); val6.Add((EDrugType)0); val5.Initialize(Singleton<PropertyUtility>.Instance.GetProperties(val4), val6, val3); NetworkSingleton<ProductManager>.Instance.createdProducts.Add((ProductDefinition)(object)val5); NetworkSingleton<ProductManager>.Instance.ProductPrices.Add((ProductDefinition)(object)val5, ((ProductDefinition)val5).MarketValue); NetworkSingleton<ProductManager>.Instance.ProductNames.Add(((ItemDefinition)val5).Name); Singleton<Registry>.Instance.AddToRegistry((ItemDefinition)(object)val5); ((ItemDefinition)val5).Icon = Singleton<ProductIconManager>.Instance.GenerateIcons(((ItemDefinition)val5).ID); RecipeRandomizerNs.Log(" Rehydrated weed via loader: " + ((ItemDefinition)val2).ID); } } } }