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 10 months 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) { } } }