Decompiled source of EnhanceDealSystems v1.1.3

EnhanceDealSystems.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using EnhanceDealSystems;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.AvatarFramework.Animation;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Dialogue;
using Il2CppScheduleOne.Economy;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Messaging;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Quests;
using Il2CppScheduleOne.UI.Handover;
using Il2CppScheduleOne.UI.Phone;
using Il2CppScheduleOne.UI.Phone.Messages;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using ModManagerPhoneApp;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(EntryPoint), "EnhanceDealSystems", "1.0.6", "_peron", null)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("EnhanceDealSystems")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EnhanceDealSystems")]
[assembly: AssemblyTitle("EnhanceDealSystems")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace EnhanceDealSystems
{
	public class EntryPoint : MelonMod
	{
		[HarmonyPatch(typeof(Player))]
		[HarmonyPatch("PlayerLoaded")]
		private class ConfigLoad
		{
			[HarmonyPostfix]
			private static void PostfixPlayerLoaded(Player __instance)
			{
				LoadAllCategories();
			}
		}

		[HarmonyPatch(typeof(Customer))]
		private class HandoverPostFix
		{
			[HarmonyPatch("ProcessHandover")]
			[HarmonyPostfix]
			private static void ProcessHandoverPostfix(Customer __instance, EHandoverOutcome outcome, Contract contract, List<ItemInstance> items, bool handoverByPlayer, bool giveBonuses = true)
			{
				float num = default(float);
				EDrugType val = default(EDrugType);
				int num2 = default(int);
				float num3 = Mathf.Clamp01(__instance.EvaluateDelivery(contract, items, ref num, ref val, ref num2));
				__instance.ChangeAddiction(num / 5f);
				float relationshipChange = CustomerSatisfaction.GetRelationshipChange(num3);
				__instance.NPC.RelationData.ChangeRelationship(relationshipChange * (float)(int)((MelonPreferences_Entry)RelationMultiplier).BoxedValue, true);
			}
		}

		[HarmonyPatch(typeof(DialogueController))]
		private class DialogTest
		{
			[HarmonyPatch("Interacted")]
			[HarmonyPrefix]
			private static bool PreInteracted(DialogueController __instance)
			{
				try
				{
					if (!(bool)((MelonPreferences_Entry)SuperAutoHandover).BoxedValue)
					{
						return true;
					}
					Customer component = ((Component)__instance.npc).gameObject.GetComponent<Customer>();
					_ = component.CurrentContract.Payment;
					if (component.IsAtDealLocation())
					{
						return DoDeal(component);
					}
					return true;
				}
				catch (Exception)
				{
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(Customer))]
		private class Handovers
		{
			[HarmonyPatch(typeof(Customer), "HandoverChosen")]
			[HarmonyPrefix]
			private static bool HandoverChosenPrefix(Customer __instance)
			{
				return DoDeal(__instance);
			}
		}

		[HarmonyPatch(typeof(DealWindowSelector))]
		[HarmonyPatch("SetIsOpen", new Type[]
		{
			typeof(bool),
			typeof(MSGConversation),
			typeof(Action<EDealWindow>)
		})]
		private class InstaClick
		{
			[HarmonyPostfix]
			private static void PostOpenWindow(DealWindowSelector __instance, bool open, MSGConversation conversation, Action<EDealWindow> callback)
			{
				if ((bool)((MelonPreferences_Entry)AutoScheduleDeals).BoxedValue)
				{
					switch ((int)((MelonPreferences_Entry)DealDayTime).BoxedValue)
					{
					case 1:
						__instance.MorningButton.Clicked();
						break;
					case 2:
						__instance.AfternoonButton.Clicked();
						break;
					case 3:
						__instance.NightButton.Clicked();
						break;
					default:
						__instance.LateNightButton.Clicked();
						break;
					}
				}
			}
		}

		[HarmonyPatch(typeof(AvatarLookController))]
		private class AvatarLook
		{
			[HarmonyPatch("UpdateShit")]
			[HarmonyPostfix]
			private static void AvatarLookController(AvatarLookController __instance)
			{
				try
				{
					if (__instance.nearestPlayerDist < 4f && (bool)((MelonPreferences_Entry)MagicHandover).BoxedValue)
					{
						Customer component = ((Component)__instance.NPC).gameObject.GetComponent<Customer>();
						_ = component.CurrentContract.Payment;
						if (component.IsAtDealLocation() && ((Behaviour)component.CurrentContract).enabled)
						{
							DoDeal(component);
							((Behaviour)component.CurrentContract).enabled = false;
							((Object)component.CurrentContract).Finalize();
						}
					}
				}
				catch (Exception)
				{
				}
			}
		}

		[HarmonyPatch(typeof(Quest))]
		private class QuestTest
		{
			private static HashSet<int> handledQuests = new HashSet<int>();

			[HarmonyPatch("SetIsTracked")]
			[HarmonyPostfix]
			private static void SetIsTrackedPrefix(Quest __instance, bool tracked)
			{
				if (tracked && !(bool)((MelonPreferences_Entry)AutoTrack).BoxedValue && __instance.title.Contains("Deal for"))
				{
					int hashCode = ((Object)__instance).GetHashCode();
					if (!handledQuests.Contains(hashCode))
					{
						handledQuests.Add(hashCode);
						__instance.SetIsTracked(false);
					}
				}
			}
		}

		[HarmonyPatch(typeof(MSGConversation))]
		private class MsgTest
		{
			[HarmonyPatch("RefreshPreviewText")]
			[HarmonyPostfix]
			public static void RefreshPreviewText(MSGConversation __instance)
			{
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Invalid comparison between Unknown and I4
				if (__instance.currentResponses.Count >= 2 && (int)__instance.bubbles[__instance.bubbles.Count - 1].alignment == 1)
				{
					if (__instance.currentResponses[1].label == "COUNTEROFFER" && (bool)((MelonPreferences_Entry)AutoCounterOffer).BoxedValue)
					{
						__instance.ResponseChosen(__instance.currentResponses[1], true);
					}
					else if (__instance.currentResponses[0].label == "ACCEPT_CONTRACT" && (bool)((MelonPreferences_Entry)AutoScheduleDeals).BoxedValue)
					{
						__instance.ResponseChosen(__instance.currentResponses[0], true);
					}
				}
			}
		}

		[HarmonyPatch(typeof(CounterofferInterface))]
		private class CounterofferInterfacePatches
		{
			private static void UpdateConfirmButtonText(CounterofferInterface instance)
			{
				if (!(bool)((MelonPreferences_Entry)AutoCounterOffer).BoxedValue || !instance.IsOpen)
				{
					return;
				}
				float num = EvaluateCounterofferPercentage(instance.selectedProduct, instance.quantity, instance.price, ((Component)instance.conversation.sender).GetComponent<Customer>());
				if (num < 70f)
				{
					instance.conversation.ResponseChosen(instance.conversation.currentResponses[0], true);
					return;
				}
				while (Mathf.RoundToInt(num) == 100)
				{
					instance.price += 1f;
					num = EvaluateCounterofferPercentage(instance.selectedProduct, instance.quantity, instance.price, ((Component)instance.conversation.sender).GetComponent<Customer>());
				}
				instance.price -= 1f;
				instance.PriceInput.text = instance.price.ToString();
				instance.Update();
				instance.Send();
				instance.IsOpen = false;
			}

			[HarmonyPatch("Open")]
			[HarmonyPostfix]
			private static void PostOpenPatch(CounterofferInterface __instance)
			{
				UpdateConfirmButtonText(__instance);
			}

			[HarmonyPatch("ChangePrice")]
			[HarmonyPostfix]
			private static void PostPriceChangePatch(CounterofferInterface __instance)
			{
				UpdateConfirmButtonText(__instance);
			}

			[HarmonyPatch("ChangeQuantity")]
			[HarmonyPostfix]
			private static void PostQuantityChangePatch(CounterofferInterface __instance)
			{
				UpdateConfirmButtonText(__instance);
			}
		}

		public static MelonPreferences_Category ConfigCategory;

		public static MelonPreferences_Entry<bool> SuperAutoHandover;

		public static MelonPreferences_Entry<bool> AutoScheduleDeals;

		public static MelonPreferences_Entry<bool> AutoCounterOffer;

		public static MelonPreferences_Entry<int> DealDayTime;

		public static MelonPreferences_Entry<bool> AutoHandOver;

		public static MelonPreferences_Entry<bool> AutoTrack;

		public static MelonPreferences_Entry<bool> MagicHandover;

		public static MelonPreferences_Entry<int> RelationMultiplier;

		public static float EvaluateCounterofferPercentage(ProductDefinition product, int quantity, float price, Customer customer)
		{
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			float adjustedWeeklySpend = customer.customerData.GetAdjustedWeeklySpend(customer.NPC.RelationData.RelationDelta / 5f);
			List<EDay> orderDays = customer.customerData.GetOrderDays(customer.CurrentAddiction, customer.NPC.RelationData.RelationDelta / 5f);
			float num = adjustedWeeklySpend / (float)orderDays.Count;
			if (price >= num * 3f)
			{
				return 0f;
			}
			float valueProposition = Customer.GetValueProposition(Registry.GetItem<ProductDefinition>(customer.OfferedContractInfo.Products.entries[0].ProductID), customer.OfferedContractInfo.Payment / (float)customer.OfferedContractInfo.Products.entries[0].Quantity);
			float productEnjoyment = customer.GetProductEnjoyment(product, StandardsMethod.GetCorrespondingQuality(customer.customerData.Standards));
			float num2 = Mathf.InverseLerp(-1f, 1f, productEnjoyment);
			float valueProposition2 = Customer.GetValueProposition(product, price / (float)quantity);
			float num3 = Mathf.Pow((float)quantity / (float)customer.OfferedContractInfo.Products.entries[0].Quantity, 0.6f);
			float num4 = Mathf.Lerp(0f, 2f, num3 * 0.5f);
			float num5 = Mathf.Lerp(1f, 0f, Mathf.Abs(num4 - 1f));
			if (valueProposition2 * num5 > valueProposition)
			{
				return 100f;
			}
			if (valueProposition2 < 0.12f)
			{
				return 0f;
			}
			float num6 = productEnjoyment * valueProposition;
			float num7 = num2 * num5 * valueProposition2;
			if (num7 > num6)
			{
				return 100f;
			}
			float num8 = num6 - num7;
			float num9 = Mathf.Lerp(0f, 1f, num8 / 0.2f);
			float num10 = Mathf.Max(customer.CurrentAddiction, customer.NPC.RelationData.NormalizedRelationDelta);
			float num11 = Mathf.Lerp(0f, 0.2f, num10);
			if (num9 <= num11)
			{
				return 100f;
			}
			if (num9 - num11 >= 0.9f)
			{
				return 0f;
			}
			return Mathf.Clamp((0.9f + num11 - num9) / 0.9f, 0f, 1f) * 100f;
		}

		public override void OnInitializeMelon()
		{
			ConfigCategory = MelonPreferences.CreateCategory("EnhanceDealSystems");
			SuperAutoHandover = ConfigCategory.CreateEntry<bool>("SuperAutoHandover", true, "Enable Super Auto Handover", (string)null, false, false, (ValueValidator)null, (string)null);
			AutoScheduleDeals = ConfigCategory.CreateEntry<bool>("AutoScheduleDeals", true, "Enable Auto Schedule Deals", (string)null, false, false, (ValueValidator)null, (string)null);
			AutoCounterOffer = ConfigCategory.CreateEntry<bool>("AutoCounterOffer", true, "Enable Auto Counter Offer", (string)null, false, false, (ValueValidator)null, (string)null);
			DealDayTime = ConfigCategory.CreateEntry<int>("DealDayTime", 4, "Deal Day Time (1=Morning, 2=Evening, 3=Night, 4=Late Night)", (string)null, false, false, (ValueValidator)null, (string)null);
			AutoHandOver = ConfigCategory.CreateEntry<bool>("AutoHandOver", true, "Enable Auto Hand Over", (string)null, false, false, (ValueValidator)null, (string)null);
			AutoTrack = ConfigCategory.CreateEntry<bool>("AutoTrack", true, "Enable Auto Track", (string)null, false, false, (ValueValidator)null, (string)null);
			MagicHandover = ConfigCategory.CreateEntry<bool>("MagicHandover", true, "Enable Magic Handover", (string)null, false, false, (ValueValidator)null, (string)null);
			RelationMultiplier = ConfigCategory.CreateEntry<int>("SatisfactionMultiplier", 1, "Satisfaction Multiplier (1=Normal, 2=Double, etc)", (string)null, false, false, (ValueValidator)null, (string)null);
			ConfigCategory.SetFilePath("UserData/EnhanceDealSystems.cfg");
			ConfigCategory.SaveToFile(true);
			try
			{
				ModSettingsEvents.OnPreferencesSaved += LoadAllCategories;
				((MelonBase)this).LoggerInstance.Msg("Successfully subscribed to Mod Manager save event.");
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Warning("Could not subscribe to Mod Manager event (Mod Manager may not be installed/compatible): " + ex.Message);
			}
		}

		public static void LoadAllCategories()
		{
			foreach (MelonPreferences_Category category in MelonPreferences.Categories)
			{
				category.LoadFromFile(true);
			}
		}

		public static bool DoDeal(Customer __instance)
		{
			if (!(bool)((MelonPreferences_Entry)AutoHandOver).BoxedValue)
			{
				return true;
			}
			Contract currentContract = __instance.CurrentContract;
			object obj;
			if (currentContract == null)
			{
				obj = null;
			}
			else
			{
				ProductList productList = currentContract.ProductList;
				obj = ((productList != null) ? productList.entries : null);
			}
			if (obj == null || __instance.CurrentContract.ProductList.entries.Count == 0)
			{
				return true;
			}
			Entry obj2 = __instance.CurrentContract.ProductList.entries[0];
			string productID = obj2.ProductID;
			uint quantity = (uint)obj2.Quantity;
			if (quantity == 0)
			{
				return true;
			}
			List<ItemSlot> list = new List<ItemSlot>();
			List<ItemSlot> list2 = new List<ItemSlot>();
			List<ItemSlot> list3 = new List<ItemSlot>();
			foreach (ItemSlot item in (Il2CppArrayBase<ItemSlot>)(object)Player.Local.Inventory)
			{
				if (((item != null) ? item.ItemInstance : null) == null || !(item.ItemInstance.ID == productID) || item.Quantity <= 0)
				{
					continue;
				}
				ItemInstance itemInstance = item.ItemInstance;
				string text = null;
				_ = ((MemberInfo)((Object)itemInstance).GetIl2CppType()).Name;
				WeedInstance val = ((Il2CppObjectBase)itemInstance).TryCast<WeedInstance>();
				if (val != null)
				{
					text = ((ProductItemInstance)val).PackagingID;
				}
				else
				{
					MethInstance val2 = ((Il2CppObjectBase)itemInstance).TryCast<MethInstance>();
					if (val2 != null)
					{
						text = ((ProductItemInstance)val2).PackagingID;
					}
					else
					{
						CocaineInstance val3 = ((Il2CppObjectBase)itemInstance).TryCast<CocaineInstance>();
						if (val3 != null)
						{
							text = ((ProductItemInstance)val3).PackagingID;
						}
					}
				}
				switch (text?.ToLower())
				{
				case "brick":
					list.Add(item);
					break;
				case "jar":
					list2.Add(item);
					break;
				case "baggie":
					list3.Add(item);
					break;
				default:
					list3.Add(item);
					break;
				}
			}
			uint num = quantity;
			List<(ItemSlot, int)> list4 = new List<(ItemSlot, int)>();
			foreach (ItemSlot item2 in list)
			{
				if (num == 0)
				{
					break;
				}
				uint num2 = num / 20;
				if (num2 == 0)
				{
					break;
				}
				uint quantity2 = (uint)item2.Quantity;
				uint num3 = Math.Min(num2, quantity2);
				if (num3 != 0)
				{
					list4.Add((item2, (int)num3));
					num -= num3 * 20;
				}
			}
			if (num != 0)
			{
				foreach (ItemSlot item3 in list2)
				{
					if (num == 0)
					{
						break;
					}
					uint num4 = num / 5;
					if (num4 == 0)
					{
						break;
					}
					uint quantity3 = (uint)item3.Quantity;
					uint num5 = Math.Min(num4, quantity3);
					if (num5 != 0)
					{
						list4.Add((item3, (int)num5));
						num -= num5 * 5;
					}
				}
			}
			if (num != 0)
			{
				foreach (ItemSlot item4 in list3)
				{
					if (num == 0)
					{
						break;
					}
					uint val4 = num;
					uint quantity4 = (uint)item4.Quantity;
					uint num6 = Math.Min(val4, quantity4);
					if (num6 != 0)
					{
						list4.Add((item4, (int)num6));
						num -= num6;
					}
				}
			}
			if (num == 0)
			{
				foreach (var item5 in list4)
				{
					item5.Item1.ChangeQuantity(-item5.Item2, false);
				}
				List<ItemInstance> val5 = new List<ItemInstance>();
				ItemDefinition val6 = Singleton<Registry>.instance._GetItem(productID, true);
				if ((Object)(object)val6 != (Object)null)
				{
					ItemInstance defaultInstance = val6.GetDefaultInstance(1);
					defaultInstance.Quantity = (int)quantity;
					val5.Add(defaultInstance);
					__instance.ProcessHandover((EHandoverOutcome)1, __instance.CurrentContract, val5, true, true);
				}
				else
				{
					MelonLogger.Error("HandoverChosenPrefix: Failed to get ItemDefinition for " + productID + ". Cannot process handover.");
				}
				return false;
			}
			MelonLogger.Warning($"HandoverChosenPrefix: Failed to fulfill contract. {num} units still needed after planning. No changes applied to inventory.");
			return true;
		}
	}
}