Decompiled source of TopShelfBonus v1.0.0

TopShelfBonus.dll

Decompiled a week ago
using 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)
		{
		}
	}
}