Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of Custom Deals v6.1.1
ScheduleIMods5.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne.Economy; using Il2CppScheduleOne.Product; using Il2CppScheduleOne.Quests; using Il2CppScheduleOne.UI.Phone.Messages; using Il2CppSystem.Collections.Generic; using JoiveCustomDeals; using MelonLoader; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Main), "Joive Custom Deals", "6.2.0", "Joive", null)] [assembly: MelonGame(null, null)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("ScheduleIMods5")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("ScheduleIMods5")] [assembly: AssemblyTitle("ScheduleIMods5")] [assembly: AssemblyVersion("1.0.0.0")] namespace JoiveCustomDeals; public class Main : MelonMod { private KeyCode menuKey = (KeyCode)283; private bool showMenu = false; private Rect windowRect = new Rect(100f, 100f, 480f, 750f); private Vector2 scrollCustomers = Vector2.zero; private Vector2 scrollProducts = Vector2.zero; private List<Customer> realCustomers = new List<Customer>(); private List<ProductDefinition> listedProducts = new List<ProductDefinition>(); private int selectedCustomerIndex = -1; private int selectedProductIndex = -1; private int inputFocus = 0; private string amountStr = "10"; private string priceStr = "500"; private int selectedQuality = 4; private string[] qualityNames = new string[5] { "Red", "Green", "Blue", "Purple", "Yellow" }; public override void OnInitializeMelon() { MelonLogger.Msg("Joive Custom Deals v6.2 (Safe GUI Fix) loaded! Press F2."); } public override void OnUpdate() { //IL_0002: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(menuKey)) { showMenu = !showMenu; if (showMenu) { ScanDatabase(); Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; } else { Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } } } public override void OnGUI() { //IL_0014: 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_0034: Unknown result type (might be due to invalid IL or missing references) if (showMenu) { try { windowRect = GUI.Window(2026, windowRect, WindowFunction.op_Implicit((Action<int>)DrawWindow), "\ud83d\udcf1 JOIVE DEAL GENERATOR v6.2"); } catch { } } } private void DrawWindow(int windowID) { //IL_0016: 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_0066: Unknown result type (might be due to invalid IL or missing references) //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_0179: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_0402: Unknown result type (might be due to invalid IL or missing references) try { GUI.DragWindow(new Rect(0f, 0f, 10000f, 25f)); GUILayout.BeginArea(new Rect(15f, 30f, ((Rect)(ref windowRect)).width - 30f, ((Rect)(ref windowRect)).height - 40f)); GUILayout.Label("<b>1. Select LIVING Customer:</b>", (Il2CppReferenceArray<GUILayoutOption>)null); scrollCustomers = GUILayout.BeginScrollView(scrollCustomers, GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(100f) }); if (realCustomers.Count == 0) { GUILayout.Label("No active customers found...", (Il2CppReferenceArray<GUILayoutOption>)null); } for (int i = 0; i < realCustomers.Count; i++) { try { Customer val = realCustomers[i]; if (!((Object)(object)val == (Object)null)) { string name = ((Il2CppObjectBase)val).Cast<Object>().name; if (!string.IsNullOrEmpty(name) && GUILayout.Toggle(selectedCustomerIndex == i, " " + name, GUIStyle.op_Implicit("Button"), Array.Empty<GUILayoutOption>())) { selectedCustomerIndex = i; } } } catch { } } GUILayout.EndScrollView(); GUILayout.Space(5f); GUILayout.Label($"<b>2. Select Listed Product (For Sale: {listedProducts.Count}):</b>", (Il2CppReferenceArray<GUILayoutOption>)null); scrollProducts = GUILayout.BeginScrollView(scrollProducts, GUI.skin.box, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(100f) }); if (listedProducts.Count == 0) { GUILayout.Label("No products listed for sale in phone!", (Il2CppReferenceArray<GUILayoutOption>)null); } for (int j = 0; j < listedProducts.Count; j++) { try { ProductDefinition val2 = listedProducts[j]; if (!((Object)(object)val2 == (Object)null)) { string name2 = ((Object)val2).name; if (!string.IsNullOrEmpty(name2) && GUILayout.Toggle(selectedProductIndex == j, " " + name2, GUIStyle.op_Implicit("Button"), Array.Empty<GUILayoutOption>())) { selectedProductIndex = j; } } } catch { } } GUILayout.EndScrollView(); GUILayout.Space(5f); GUILayout.BeginVertical(GUI.skin.box, (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); if (GUILayout.Toggle(inputFocus == 0, "AMOUNT:\n" + amountStr + "g", GUIStyle.op_Implicit("Button"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { inputFocus = 0; } if (GUILayout.Toggle(inputFocus == 1, "PRICE:\n$" + priceStr, GUIStyle.op_Implicit("Button"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { inputFocus = 1; } GUILayout.EndHorizontal(); DrawNumpad(); GUILayout.Space(10f); GUILayout.Label("Quality: " + qualityNames[selectedQuality], (Il2CppReferenceArray<GUILayoutOption>)null); GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); for (int k = 0; k < qualityNames.Length; k++) { if (GUILayout.Toggle(selectedQuality == k, qualityNames[k], GUIStyle.op_Implicit("Button"), Array.Empty<GUILayoutOption>())) { selectedQuality = k; } } GUILayout.EndHorizontal(); GUILayout.EndVertical(); GUILayout.Space(10f); GUI.backgroundColor = Color.green; if (GUILayout.Button("SEND DEAL TO PHONE", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) })) { CreateCustomDeal(); } GUI.backgroundColor = Color.white; if (GUILayout.Button("CLOSE MENU", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(25f) })) { showMenu = false; Cursor.lockState = (CursorLockMode)1; Cursor.visible = false; } GUILayout.EndArea(); } catch (Exception ex) { MelonLogger.Error("GUI Crash Prevented: " + ex.Message); } } private void DrawNumpad() { string[] array = new string[12] { "7", "8", "9", "4", "5", "6", "1", "2", "3", "C", "0", "<" }; int num = 0; for (int i = 0; i < 4; i++) { GUILayout.BeginHorizontal((Il2CppReferenceArray<GUILayoutOption>)null); for (int j = 0; j < 3; j++) { if (GUILayout.Button(array[num], (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) })) { HandleNumpadInput(array[num]); } num++; } GUILayout.EndHorizontal(); } } private void HandleNumpadInput(string key) { string text = ((inputFocus == 0) ? amountStr : priceStr); if (key == "C") { text = ""; } else if (key == "<") { if (text.Length > 0) { text = text.Substring(0, text.Length - 1); } } else { text += key; } if (text.Length > 8) { text = text.Substring(0, 8); } if (inputFocus == 0) { amountStr = text; } else { priceStr = text; } } private void ScanDatabase() { realCustomers.Clear(); try { Il2CppArrayBase<Customer> val = Object.FindObjectsOfType<Customer>(); foreach (Customer item in val) { try { if ((Object)(object)item != (Object)null && item.offerDealChoice != null) { string name = ((Il2CppObjectBase)item).Cast<Object>().name; if (!string.IsNullOrEmpty(name)) { realCustomers.Add(item); } } } catch { } } realCustomers.Sort((Customer a, Customer b) => string.Compare(((Il2CppObjectBase)a).Cast<Object>().name, ((Il2CppObjectBase)b).Cast<Object>().name)); } catch { } listedProducts.Clear(); try { List<ProductDefinition> val2 = ProductManager.ListedProducts; if (val2 != null) { Enumerator<ProductDefinition> enumerator2 = val2.GetEnumerator(); while (enumerator2.MoveNext()) { ProductDefinition current2 = enumerator2.Current; try { if ((Object)(object)current2 != (Object)null && !string.IsNullOrEmpty(((Object)current2).name)) { listedProducts.Add(current2); } } catch { } } } } catch { } if (selectedCustomerIndex >= realCustomers.Count) { selectedCustomerIndex = -1; } if (selectedProductIndex >= listedProducts.Count) { selectedProductIndex = -1; } } private void CreateCustomDeal() { //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Expected O, but got Unknown //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Expected O, but got Unknown //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown if (selectedCustomerIndex == -1 || selectedCustomerIndex >= realCustomers.Count || selectedProductIndex == -1 || selectedProductIndex >= listedProducts.Count) { return; } Customer val = realCustomers[selectedCustomerIndex]; ProductDefinition val2 = listedProducts[selectedProductIndex]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return; } int.TryParse(amountStr, out var result); int.TryParse(priceStr, out var result2); MelonLogger.Msg($"[CustomDeal] Hijacking native contract for: {((Il2CppObjectBase)val).Cast<Object>().name} | {result}x {((Object)val2).name} | ${result2}"); try { MethodInfo method = typeof(Customer).GetMethod("TryGenerateContract", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { MelonLogger.Error("Could not find TryGenerateContract method!"); return; } ContractInfo val3 = null; try { val3 = (ContractInfo)method.Invoke(val, new object[1] { val.AssignedDealer }); } catch { val3 = (ContractInfo)method.Invoke(val, new object[1]); } if (val3 == null) { MelonLogger.Msg("Target customer is on cooldown. Searching for a surrogate contract..."); foreach (Customer realCustomer in realCustomers) { if (!((Object)(object)realCustomer == (Object)null) && !((Object)(object)realCustomer == (Object)(object)val)) { try { val3 = (ContractInfo)method.Invoke(realCustomer, new object[1] { realCustomer.AssignedDealer }); } catch { val3 = (ContractInfo)method.Invoke(realCustomer, new object[1]); } if (val3 != null) { MelonLogger.Msg("Found a surrogate contract from " + ((Il2CppObjectBase)realCustomer).Cast<Object>().name + ". Repurposing..."); break; } } } } if (val3 == null) { MelonLogger.Error("Native generator returned null for ALL customers. Wait a bit or try later."); return; } val3.Payment = result2; if (val3.Products != null && val3.Products.entries != null) { val3.Products.entries.Clear(); } else { val3.Products = new ProductList(); val3.Products.entries = new List<Entry>(); } string text = ((Object)val2).name; PropertyInfo[] properties = ((object)val2).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.PropertyType == typeof(string) && (propertyInfo.Name.ToLower() == "productid" || propertyInfo.Name.ToLower() == "id")) { try { text = (string)propertyInfo.GetValue(val2, null); } catch { continue; } break; } } if (text == ((Object)val2).name) { FieldInfo[] fields = ((object)val2).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.FieldType == typeof(string) && (fieldInfo.Name.ToLower() == "productid" || fieldInfo.Name.ToLower() == "id")) { try { text = (string)fieldInfo.GetValue(val2); } catch { continue; } break; } } } Entry val4 = new Entry(); PropertyInfo[] properties2 = typeof(Entry).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo2 in properties2) { if (!propertyInfo2.CanWrite) { continue; } string text2 = propertyInfo2.Name.ToLower(); try { if (text2.Contains("product") || text2.Contains("item") || text2.Contains("def") || text2.Contains("drug")) { if (propertyInfo2.PropertyType == typeof(string)) { propertyInfo2.SetValue(val4, text, null); } else { propertyInfo2.SetValue(val4, val2, null); } } else if (text2.Contains("quant") || text2.Contains("amount")) { propertyInfo2.SetValue(val4, result, null); } else if (text2.Contains("qual")) { propertyInfo2.SetValue(val4, Enum.ToObject(propertyInfo2.PropertyType, selectedQuality), null); } } catch { } } FieldInfo[] fields2 = typeof(Entry).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields2) { string text3 = fieldInfo2.Name.ToLower(); try { if (text3.Contains("product") || text3.Contains("item") || text3.Contains("def") || text3.Contains("drug")) { if (fieldInfo2.FieldType == typeof(string)) { fieldInfo2.SetValue(val4, text); } else { fieldInfo2.SetValue(val4, val2); } } else if (text3.Contains("quant") || text3.Contains("amount")) { fieldInfo2.SetValue(val4, result); } else if (text3.Contains("qual")) { fieldInfo2.SetValue(val4, Enum.ToObject(fieldInfo2.FieldType, selectedQuality)); } } catch { } } val3.Products.entries.Add(val4); val.OfferContract(val3); MelonLogger.Msg("✅ SUCCESS! Hacked contract sent!"); MessagesApp val5 = Object.FindObjectOfType<MessagesApp>(); if ((Object)(object)val5 != (Object)null) { val5.RefreshNotifications(); val5.RepositionEntries(); } } catch (Exception ex) { MelonLogger.Error("Injection failed: " + ex.Message); } } }