Decompiled source of BusinessAsUsual v1.0.1

BusinessAsUsual.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.Extensions;
using SOD.Common.Helpers;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("BusinessAsUsual")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BusinessAsUsual")]
[assembly: AssemblyTitle("BusinessAsUsual")]
[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 BusinessAsUsual
{
	[BepInPlugin("Severedsolo.SOD.BusinessAsUsual", "BusinessAsUsual", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BusinessAsUsual : BasePlugin
	{
		public const string PLUGIN_GUID = "Severedsolo.SOD.BusinessAsUsual";

		public const string PLUGIN_NAME = "BusinessAsUsual";

		public const string PLUGIN_VERSION = "1.0.0";

		public static BusinessAsUsual Instance;

		public static Random Random = new Random();

		private static ConfigEntry<bool> debugMode { get; set; }

		public override void Load()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			new Harmony("Severedsolo.SOD.BusinessAsUsual").PatchAll(Assembly.GetExecutingAssembly());
			Lib.Time.OnTimeInitialized += AddTimeEvents;
			Lib.SaveGame.OnAfterNewGame += ResetMod;
			Lib.SaveGame.OnAfterLoad += ResetMod;
			debugMode = ((BasePlugin)this).Config.Bind<bool>("Debugging", "BusinessAsUsual.DebuggingEnabled", false, "Debugging Enabled");
			LogInfo("Plugin is initialised", forcePrint: true);
		}

		private void ResetMod(object? sender, EventArgs e)
		{
			LoadBlacklist();
			PatchUpdateGameLocation.AlreadyCheckedPeople.Clear();
			PatchUpdateGameLocation.BusinessesWithSaleRecords.Clear();
			LogInfo("All data reset", forcePrint: true);
		}

		private void LoadBlacklist()
		{
			PatchUpdateGameLocation.BlacklistedProducts.Clear();
			string pluginDirectoryPath = Lib.SaveGame.GetPluginDirectoryPath(Assembly.GetExecutingAssembly());
			if (Utility.IsNullOrWhiteSpace(pluginDirectoryPath))
			{
				return;
			}
			pluginDirectoryPath = Path.Combine(pluginDirectoryPath, "blacklist.txt");
			if (!File.Exists(pluginDirectoryPath))
			{
				((BasePlugin)this).Log.LogWarning((object)("Blacklist file (expected to be at " + pluginDirectoryPath + ") does not exist!"));
				return;
			}
			int num = 0;
			using (StreamReader streamReader = new StreamReader(pluginDirectoryPath))
			{
				while (true)
				{
					string text = streamReader.ReadLine();
					if (text == null)
					{
						break;
					}
					PatchUpdateGameLocation.BlacklistedProducts.Add(text);
					num++;
					LogInfo("Added " + text + " to blacklist", forcePrint: true);
				}
			}
			LogInfo("Loaded " + num + " items from blacklist", forcePrint: true);
		}

		private void AddTimeEvents(object? sender, TimeChangedArgs e)
		{
			Lib.Time.OnHourChanged += CheckIfNeedToBackFillRecords;
		}

		private void CheckIfNeedToBackFillRecords(object? sender, TimeChangedArgs e)
		{
			PatchUpdateGameLocation.CreateFakeRecords();
		}

		public void LogInfo(string messageToLog, bool forcePrint = false)
		{
			if (forcePrint || debugMode.Value)
			{
				((BasePlugin)this).Log.LogInfo((object)messageToLog);
			}
		}
	}
	[HarmonyPatch(typeof(Human), "OnGameLocationChange")]
	public class PatchUpdateGameLocation
	{
		public static Dictionary<string, Company> BusinessesWithSaleRecords = new Dictionary<string, Company>();

		public static Dictionary<string, string?> AlreadyCheckedPeople = new Dictionary<string, string>();

		public static List<string> BlacklistedProducts = new List<string>();

		[HarmonyPostfix]
		public static void Postfix(Human __instance)
		{
			if ((Object)(object)__instance == (Object)null || ((Actor)__instance).isPlayer || ((Actor)__instance).isMachine || ((Actor)__instance).isHomeless)
			{
				return;
			}
			if (BusinessesWithSaleRecords.Count == 0)
			{
				FindBusinessesWithSalesRecords();
			}
			object obj;
			if (__instance == null)
			{
				obj = null;
			}
			else
			{
				NewGameLocation currentGameLocation = ((Actor)__instance).currentGameLocation;
				obj = ((currentGameLocation != null) ? currentGameLocation.thisAsAddress : null);
			}
			if ((Object)obj == (Object)null || !BusinessesWithSaleRecords.TryGetValue(((Object)((Actor)__instance).currentGameLocation.thisAsAddress).name, out Company value) || value.companyRoster.Contains(__instance.job))
			{
				return;
			}
			AlreadyCheckedPeople.TryGetValue(((Object)__instance).name, out string value2);
			if (Utility.IsNullOrWhiteSpace(value2) || !(value2 == value.name))
			{
				BusinessAsUsual.Instance.LogInfo(((Object)__instance).name + " is visiting " + ((Object)((Actor)__instance).currentGameLocation.thisAsAddress).name);
				AlreadyCheckedPeople[((Object)__instance).name] = value.name;
				if (IsValidToGenerateRecord(value, __instance))
				{
					SimulateSalesRecord(value, __instance);
				}
			}
		}

		private static bool IsValidToGenerateRecord(Company c, Human human)
		{
			int num = NumberOfRecordsInLast24Hours(c, human);
			int num2 = NumberOfRecordsToGenerate(c);
			if (num != int.MaxValue)
			{
				BusinessAsUsual.Instance.LogInfo(c.name + " has " + num + " sales records out of " + num2);
			}
			if (num <= num2)
			{
				return (Object)(object)human != (Object)(object)MurderController.Instance.currentMurderer;
			}
			return false;
		}

		private static int NumberOfRecordsToGenerate(Company c)
		{
			return c.prices.Count;
		}

		private static int NumberOfRecordsInLast24Hours(Company company, Human human)
		{
			float num = SessionData.Instance.gameTime - 24f;
			int num2 = 0;
			List<SalesRecord> list = EnumerableExtensions.ToList<SalesRecord>(company.sales);
			int num3 = 0;
			for (int num4 = list.Count - 1; num4 >= 0; num4--)
			{
				SalesRecord val = list[num4];
				if (val != null)
				{
					if ((Object)(object)human != (Object)null && (Object)(object)val.GetPunter() == (Object)(object)human)
					{
						BusinessAsUsual.Instance.LogInfo("Punter already has a record");
						return int.MaxValue;
					}
					if (val.time < num)
					{
						company.sales.Remove(val);
						num2--;
						num3++;
					}
					num2++;
				}
			}
			if (num3 > 0)
			{
				BusinessAsUsual.Instance.LogInfo("Deleted " + num3 + " records from " + company.name + " as they were over 24 hours old");
			}
			return num2;
		}

		private static bool SimulateSalesRecord(Company c, Human visitor, bool forceCreate = false, bool generateFakeTimeStamp = false)
		{
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			double num = BusinessAsUsual.Random.NextDouble();
			double num2 = 1.0 - (double)NumberOfRecordsInLast24Hours(c, visitor) / (double)NumberOfRecordsToGenerate(c);
			if (!forceCreate)
			{
				BusinessAsUsual.Instance.LogInfo("Rolled " + num + " needed " + num2);
			}
			if (!forceCreate && num2 < num)
			{
				return false;
			}
			if (c.prices.Count == 0 || !c.preset.recordSalesData || c.preset.isSelfEmployed)
			{
				return false;
			}
			BusinessAsUsual.Instance.LogInfo("Attempting to create fake record for " + ((Object)visitor).name + " in " + c.name);
			int num3 = BusinessAsUsual.Random.Next(0, c.prices.Count);
			List<InteractablePreset> val = new List<InteractablePreset>();
			Enumerator<InteractablePreset, int> enumerator = c.prices.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<InteractablePreset, int> current = enumerator.Current;
				if (num3 != 0)
				{
					num3--;
					continue;
				}
				InteractablePreset key = current.Key;
				if (!((SoCustomComparison)(object)key == (SoCustomComparison)null) && !ProductIsBlacklisted(((Object)key).name.ToLower()) && !AlreadyHasItemPicked(visitor, key))
				{
					val.Add(key);
					BusinessAsUsual.Instance.LogInfo(((Object)visitor).name + " is buying a " + ((Object)key).name);
					MurderWeaponPreset weapon = key.weapon;
					if (weapon == null || !(weapon.ammunition?.Count > 0))
					{
						break;
					}
					key = EnumerableExtensions.ToList<InteractablePreset>(key.weapon.ammunition)[BusinessAsUsual.Random.Next(0, key.weapon.ammunition.Count)];
					if (!AlreadyHasItemPicked(visitor, key))
					{
						val.Add(key);
						break;
					}
				}
			}
			if (val.Count == 0)
			{
				return false;
			}
			InteractablePreset[] array = Il2CppArrayBase<InteractablePreset>.op_Implicit(val.ToArray());
			for (int i = 0; i < val.Count; i++)
			{
				InteractablePreset val2 = array[i];
				if (!((SoCustomComparison)(object)val2 == (SoCustomComparison)null))
				{
					Interactable obj = InteractableCreator.Instance.CreateWorldInteractable(val2, visitor, visitor, (Human)null, Vector3.zero, Vector3.zero, (List<Passed>)null, (Object)null, "");
					if (obj != null)
					{
						obj.SetInInventory(visitor);
					}
				}
			}
			float num4 = (generateFakeTimeStamp ? FakeTimeStamp() : SessionData.Instance.gameTime);
			c.AddSalesRecord(visitor, val, num4);
			BusinessAsUsual.Instance.LogInfo("Fake record created");
			return true;
		}

		private static bool ProductIsBlacklisted(string productName)
		{
			for (int i = 0; i < BlacklistedProducts.Count; i++)
			{
				string value = BlacklistedProducts[i].ToLower();
				if (productName.Contains(value))
				{
					return true;
				}
			}
			return false;
		}

		private static bool AlreadyHasItemPicked(Human visitor, InteractablePreset ip)
		{
			Interactable[] array = Il2CppArrayBase<Interactable>.op_Implicit(((Actor)visitor).inventory.ToArray());
			foreach (Interactable val in array)
			{
				if ((SoCustomComparison)(object)val.preset == (SoCustomComparison)(object)ip)
				{
					return true;
				}
				if ((SoCustomComparison)(object)ip.weapon != (SoCustomComparison)null && (SoCustomComparison)(object)val.preset.weapon != (SoCustomComparison)null)
				{
					if (ip.weapon.ammunition == null && val.preset.weapon.ammunition == null)
					{
						return true;
					}
					if (ip.weapon.ammunition != null && val.preset.weapon.ammunition != null)
					{
						return true;
					}
				}
			}
			return false;
		}

		private static float FakeTimeStamp()
		{
			return SessionData.Instance.gameTime - (float)BusinessAsUsual.Random.Next(1, 24) + (float)BusinessAsUsual.Random.NextDouble();
		}

		private static void FindBusinessesWithSalesRecords()
		{
			List<Company> list = EnumerableExtensions.ToList<Company>(CityData.Instance.companyDirectory);
			for (int i = 0; i < list.Count; i++)
			{
				Company val = list[i];
				if (val != null && val.prices.Count != 0 && val.preset.recordSalesData && !val.preset.isSelfEmployed && !BusinessesWithSaleRecords.Keys.Contains(((Object)val.address).name))
				{
					BusinessesWithSaleRecords.Add(((Object)val.address).name, val);
					BusinessAsUsual.Instance.LogInfo(val.name + " is at " + ((Object)val.address).name);
				}
			}
		}

		public static void CreateFakeRecords()
		{
			List<Company> list = BusinessesWithSaleRecords.Values.ToList();
			List<Human> potentialCitizens = new List<Human>((IEnumerable<Human>)EnumerableExtensions.ToList<Citizen>(CityData.Instance.citizenDirectory));
			for (int i = 0; i < list.Count; i++)
			{
				Company val = list[i];
				if (val == null)
				{
					continue;
				}
				int num = NumberOfRecordsToGenerate(val) / 4;
				int num2 = NumberOfRecordsInLast24Hours(val, null);
				BusinessAsUsual.Instance.LogInfo(val.name + " has " + num2 + "/" + num + " records");
				if (num2 >= num)
				{
					continue;
				}
				int num3 = 0;
				while (num > 0)
				{
					Human fakeCitizen = GetFakeCitizen(potentialCitizens);
					if (SimulateSalesRecord(val, fakeCitizen, forceCreate: true, generateFakeTimeStamp: true))
					{
						num--;
						num3++;
					}
				}
				BusinessAsUsual.Instance.LogInfo("Created " + num3 + " fake records for " + val.name);
			}
		}

		private static Human GetFakeCitizen(List<Human> potentialCitizens)
		{
			Human val;
			do
			{
				val = potentialCitizens[BusinessAsUsual.Random.Next(0, potentialCitizens.Count)];
			}
			while (!((Object)(object)val != (Object)null) || ((Actor)val).isDead || ((Actor)val).isPlayer || !((Object)(object)val != (Object)(object)MurderController.Instance.currentMurderer) || ((Actor)val).isHomeless);
			return val;
		}
	}
}