Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of TopShelfBonus v1.0.0
TopShelfBonus.dll
Decompiled a week agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using MelonLoader; using ScheduleOne.Economy; using ScheduleOne.ItemFramework; using ScheduleOne.Product; using ScheduleOne.Quests; using ScheduleOne.UI.Handover; using TopShelfBonus; 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(global::TopShelfBonus.TopShelfBonus), "TopShelfBonus-Mono", "1.0.0", "Archie", "Adds 5% bonus for delivering items with quality above the customer's required standards.")] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: HarmonyDontPatchAll] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("TopShelfBonus")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+4dabe0d2ed0653144adf1c875957b1371e6e72c6")] [assembly: AssemblyProduct("TopShelfBonus")] [assembly: AssemblyTitle("TopShelfBonus")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] namespace TopShelfBonus { public static class DebugConfig { public static bool EnableDebugLogs; } public class TopShelfBonus : MelonMod { public override void OnInitializeMelon() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown MelonLogger.Msg("TopShelfBonus-Mono initialized."); try { Harmony val = new Harmony("com.Archie.TopShelfBonus"); val.PatchAll(typeof(CustomerProcessHandoverPatch)); if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg("Harmony patches applied for CustomerProcessHandoverPatch."); LogHarmonyPatches(val); } } catch (Exception ex) { MelonLogger.Error("Failed to apply Harmony patches: " + ex.Message + "\n" + ex.StackTrace); } } private static void LogHarmonyPatches(Harmony harmony) { IEnumerable<MethodBase> patchedMethods = harmony.GetPatchedMethods(); foreach (MethodBase item in patchedMethods) { MelonLogger.Msg("Patched method: " + item.DeclaringType.FullName + "." + item.Name); } } } [HarmonyPatch(typeof(Customer), "ProcessHandover", new Type[] { typeof(EHandoverOutcome), typeof(Contract), typeof(List<ItemInstance>), typeof(bool), typeof(bool) })] public static class CustomerProcessHandoverPatch { [HarmonyTranspiler] public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0352: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Expected O, but got Unknown //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Expected O, but got Unknown //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Expected O, but got Unknown //IL_038b: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Expected O, but got Unknown //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Expected O, but got Unknown if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg("Transpiler started for Customer.ProcessHandover."); } List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = -1; if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg("Dumping IL instructions:"); for (int i = 0; i < list.Count; i++) { MelonLogger.Msg($"IL_{i:D4}: {list[i].opcode} {list[i].operand}"); } } for (int j = 0; j < list.Count - 1; j++) { if (list[j].opcode == OpCodes.Newobj && list[j].operand is ConstructorInfo constructorInfo && constructorInfo.DeclaringType == typeof(List<BonusPayment>) && list[j + 1].opcode == OpCodes.Stloc_S) { num = j + 2; if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg($"Found list initialization at IL_{j:D4}, inserting at IL_{num:D4}"); } break; } } if (num == -1) { if (DebugConfig.EnableDebugLogs) { MelonLogger.Error("Transpiler failed: Could not find List<Contract.BonusPayment> initialization. Dumping operand types for newobj:"); } for (int k = 0; k < list.Count; k++) { if (list[k].opcode == OpCodes.Newobj) { MelonLogger.Msg($"IL_{k:D4}: newobj operand = {list[k].operand?.GetType().Name}, {list[k].operand}"); } } return list; } if (!(((IEnumerable<CodeInstruction>)list).FirstOrDefault((Func<CodeInstruction, bool>)((CodeInstruction c) => c.opcode == OpCodes.Stloc_S && c.operand is LocalBuilder localBuilder2 && localBuilder2.LocalType == typeof(List<BonusPayment>)))?.operand is LocalBuilder localBuilder)) { MelonLogger.Error("Transpiler failed: Could not determine list local index for List<Contract.BonusPayment>."); return list; } if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg($"Found list local index: {localBuilder.LocalIndex}"); } if (DebugConfig.EnableDebugLogs && num > 0) { MelonLogger.Msg("Checking for branches before insertion point:"); for (int l = Math.Max(0, num - 10); l < num; l++) { if (list[l].opcode == OpCodes.Br || list[l].opcode == OpCodes.Brfalse || list[l].opcode == OpCodes.Brtrue) { MelonLogger.Msg($"Branch at IL_{l:D4}: {list[l].opcode} to {list[l].operand}"); } } } List<CodeInstruction> list2 = new List<CodeInstruction>(); list2.Add(new CodeInstruction(OpCodes.Ldloc_S, (object)localBuilder)); list2.Add(new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list2.Add(new CodeInstruction(OpCodes.Ldarg_2, (object)null)); list2.Add(new CodeInstruction(OpCodes.Ldarg_3, (object)null)); list2.Add(new CodeInstruction(OpCodes.Call, (object)typeof(CustomerProcessHandoverPatch).GetMethod("AddTopShelfBonus"))); List<CodeInstruction> collection = list2; list.InsertRange(num, collection); if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg("Transpiler successfully patched ProcessHandover with TopShelfBonus logic."); } return list; } public static void AddTopShelfBonus(List<BonusPayment> list, Customer customer, Contract contract, List<ItemInstance> items) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Expected I4, but got Unknown //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Expected I4, but got Unknown //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Expected O, but got Unknown try { if (DebugConfig.EnableDebugLogs) { object[] obj = new object[4] { (Object)(object)customer != (Object)null, list != null, null, null }; int num; if (customer == null) { num = 0; } else { CustomerData customerData = customer.customerData; if (customerData == null) { num = 0; } else { _ = customerData.Standards; num = 1; } } obj[2] = (byte)num != 0; obj[3] = (Object)(object)contract != (Object)null; MelonLogger.Msg(string.Format("AddTopShelfBonus invoked: {0} {1} {2} {3}", obj)); } if (!((Object)(object)customer == (Object)null) && list != null && customer != null) { CustomerData customerData2 = customer.customerData; if (customerData2 != null) { _ = customerData2.Standards; if (0 == 0) { if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg($"Existing bonuses in list (Count={list.Count}):"); foreach (BonusPayment item2 in list) { MelonLogger.Msg($" Bonus: {item2.Title}, Amount={item2.Amount}"); } } if (list.Any((BonusPayment b) => b.Title == "Quality Bonus")) { if (DebugConfig.EnableDebugLogs) { MelonLogger.Warning("AddTopShelfBonus: Quality Bonus already exists in list, skipping."); } return; } int num2 = (int)StandardsMethod.GetCorrespondingQuality(customer.customerData.Standards); int num3 = 0; int num4 = 0; if (items == null || items.Count == 0) { if (DebugConfig.EnableDebugLogs) { MelonLogger.Warning("AddTopShelfBonus: items list is null or empty."); } } else { foreach (ItemInstance item3 in items) { if (item3 == null) { if (DebugConfig.EnableDebugLogs) { MelonLogger.Warning("AddTopShelfBonus: item is null."); } continue; } ProductItemInstance val = (ProductItemInstance)(object)((item3 is ProductItemInstance) ? item3 : null); if (val != null) { int num5 = (int)((QualityItemInstance)val).Quality; num4++; if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg($"Item {item3.ID}: Quality={num5}, Required={num2}"); } if (num5 > num2) { num3 += num5 - num2; } } else if (DebugConfig.EnableDebugLogs) { MelonLogger.Warning("ItemInstance " + item3.ID + " is not a ProductItemInstance. Type: " + ((object)item3).GetType().Name); } } } if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg($"Calculated totalExcessLevels={num3}, bonusAmount={((num3 > 0) ? ((float)num3 * 0.05f * contract.Payment) : 0f)}, totalItems={num4}"); } if (num3 > 0) { float num6 = (float)num3 * 0.05f * contract.Payment; if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg($"Creating BonusPayment: Title=Quality Bonus, Amount={num6}"); } try { BonusPayment item = new BonusPayment("Quality Bonus", num6); list.Add(item); if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg($"Quality Bonus added: Amount={num6}, Average Quality={(float)num3 / (float)num4:F2}, Required Quality={num2}, Total Items={num4}"); } return; } catch (Exception ex) { MelonLogger.Error("BonusPayment creation failed: " + ex.Message + "\n" + ex.StackTrace); return; } } if (DebugConfig.EnableDebugLogs) { MelonLogger.Msg($"No Quality Bonus added: totalExcessLevels={num3}, Required Quality={num2}, Total Items={num4}"); } return; } } } MelonLogger.Error("AddQualityBonus skipped: Invalid parameters."); } catch (Exception ex2) { MelonLogger.Error("AddTopShelfBonus failed: " + ex2.Message); } } [HarmonyPrefix] public static bool Prefix(EHandoverOutcome outcome, bool giveBonuses, bool handoverByPlayer) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) if (DebugConfig.EnableDebugLogs) { string text = Guid.NewGuid().ToString().Substring(0, 8); MelonLogger.Msg($"ProcessHandover Prefix [CallID={text}]: outcome={outcome}, giveBonuses={giveBonuses}, handoverByPlayer={handoverByPlayer}"); } return true; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }