Decompiled source of MurderItemSpawner v1.1.1

MurderItemSpawner.dll

Decompiled 2 months ago
using System;
using System.Collections;
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 System.Text;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using HarmonyLib;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using SOD.Common;
using SOD.Common.BepInEx;
using UnityEngine;
using UniverseLib;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MurderItemSpawner")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+fd18034234b1bc5b3744e48ee190066c38503ea8")]
[assembly: AssemblyProduct("MurderItemSpawner")]
[assembly: AssemblyTitle("MurderItemSpawner")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MurderItemSpawner;

public class ConfigManager
{
	private static ConfigManager _instance;

	private Dictionary<string, bool> triggeredRules = new Dictionary<string, bool>();

	private Dictionary<string, bool> spawnedItems = new Dictionary<string, bool>();

	private Dictionary<string, string> itemSpawnEvents = new Dictionary<string, string>();

	private Dictionary<string, int> triggerCounts = new Dictionary<string, int>();

	private string currentCaseId = "";

	public static ConfigManager Instance
	{
		get
		{
			if (_instance == null)
			{
				_instance = new ConfigManager();
			}
			return _instance;
		}
	}

	public List<ModConfig> Configs { get; private set; } = new List<ModConfig>();


	private string ConfigFolderPath => Path.Combine(Paths.PluginPath, "ShaneeexD-MurderItemSpawner");

	private ConfigManager()
	{
		LoadConfig();
		LoadTrackingData();
	}

	public void ResetTracking()
	{
		Plugin.LogDebug("Resetting item spawn tracking for new murder case");
		triggeredRules.Clear();
		spawnedItems.Clear();
		itemSpawnEvents.Clear();
		triggerCounts.Clear();
		SaveTrackingData();
	}

	private string GetCurrentSaveFileName()
	{
		if ((Object)(object)RestartSafeController.Instance != (Object)null && RestartSafeController.Instance.saveStateFileInfo != null)
		{
			return ((FileSystemInfo)RestartSafeController.Instance.saveStateFileInfo).Name;
		}
		return "DEFAULT_SAVE";
	}

	private List<string> GetAllSaveFileNames()
	{
		List<string> list = new List<string>();
		list.Add(GetCurrentSaveFileName());
		if (GetCurrentSaveFileName() != "DEFAULT_SAVE")
		{
			list.Add("DEFAULT_SAVE");
		}
		return list;
	}

	public void SaveTrackingData()
	{
		//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ce: Expected O, but got Unknown
		try
		{
			string text = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				text = ((Object)MurderController.Instance.chosenMO).name;
			}
			StringBuilder stringBuilder = new StringBuilder();
			foreach (KeyValuePair<string, bool> spawnedItem in spawnedItems)
			{
				stringBuilder.Append(spawnedItem.Key).Append(":").Append(spawnedItem.Value ? "1" : "0")
					.Append(",");
			}
			StringBuilder stringBuilder2 = new StringBuilder();
			foreach (KeyValuePair<string, string> itemSpawnEvent in itemSpawnEvents)
			{
				stringBuilder2.Append(itemSpawnEvent.Key).Append(":").Append(itemSpawnEvent.Value)
					.Append(",");
			}
			StringBuilder stringBuilder3 = new StringBuilder();
			foreach (KeyValuePair<string, bool> triggeredRule in triggeredRules)
			{
				stringBuilder3.Append(triggeredRule.Key).Append(":").Append(triggeredRule.Value ? "1" : "0")
					.Append(",");
			}
			StringBuilder stringBuilder4 = new StringBuilder();
			foreach (KeyValuePair<string, int> triggerCount in triggerCounts)
			{
				stringBuilder4.Append(triggerCount.Key).Append(":").Append(triggerCount.Value)
					.Append(",");
			}
			string currentSaveFileName = GetCurrentSaveFileName();
			PlayerPrefs.SetString("MIS_" + currentSaveFileName + "_CurrentCaseId", text);
			PlayerPrefs.SetString("MIS_" + currentSaveFileName + "_SpawnedItems", stringBuilder.ToString());
			PlayerPrefs.SetString("MIS_" + currentSaveFileName + "_ItemSpawnEvents", stringBuilder2.ToString());
			PlayerPrefs.SetString("MIS_" + currentSaveFileName + "_TriggeredRules", stringBuilder3.ToString());
			PlayerPrefs.SetString("MIS_" + currentSaveFileName + "_TriggerCounts", stringBuilder4.ToString());
			Plugin.LogDebug("Saved tracking data for save file: " + currentSaveFileName + ", case ID: " + text);
			PlayerPrefs.Save();
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(28, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error saving tracking data: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}

	public void LoadTrackingData()
	{
		//IL_048d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0494: Expected O, but got Unknown
		try
		{
			string currentSaveFileName = GetCurrentSaveFileName();
			string text = null;
			if (PlayerPrefs.HasKey("MIS_" + currentSaveFileName + "_CurrentCaseId"))
			{
				text = currentSaveFileName;
				Plugin.LogDebug("Found tracking data for current save file: " + currentSaveFileName);
			}
			else if (currentSaveFileName != "DEFAULT_SAVE" && PlayerPrefs.HasKey("MIS_DEFAULT_SAVE_CurrentCaseId"))
			{
				text = "DEFAULT_SAVE";
				Plugin.LogDebug("No data for current save file, using DEFAULT_SAVE as fallback");
			}
			if (text == null)
			{
				Plugin.LogDebug("No saved tracking data found for save file: " + currentSaveFileName);
				ResetTracking();
				return;
			}
			string @string = PlayerPrefs.GetString("MIS_" + text + "_CurrentCaseId");
			string text2 = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				text2 = ((Object)MurderController.Instance.chosenMO).name;
			}
			if (!string.IsNullOrEmpty(text2) && @string != text2)
			{
				Plugin.LogDebug($"New case detected (old: {@string}, new: {text2}). Resetting tracking.");
				ResetTracking();
				return;
			}
			spawnedItems.Clear();
			itemSpawnEvents.Clear();
			triggeredRules.Clear();
			triggerCounts.Clear();
			if (PlayerPrefs.HasKey("MIS_" + text + "_SpawnedItems"))
			{
				string string2 = PlayerPrefs.GetString("MIS_" + text + "_SpawnedItems");
				string[] array = string2.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				string[] array2 = array;
				foreach (string text3 in array2)
				{
					string[] array3 = text3.Split(':');
					if (array3.Length == 2)
					{
						spawnedItems[array3[0]] = array3[1] == "1";
					}
				}
			}
			if (PlayerPrefs.HasKey("MIS_" + text + "_ItemSpawnEvents"))
			{
				string string3 = PlayerPrefs.GetString("MIS_" + text + "_ItemSpawnEvents");
				string[] array4 = string3.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				string[] array5 = array4;
				foreach (string text4 in array5)
				{
					string[] array6 = text4.Split(':');
					if (array6.Length == 2)
					{
						itemSpawnEvents[array6[0]] = array6[1];
					}
				}
			}
			if (PlayerPrefs.HasKey("MIS_" + text + "_TriggeredRules"))
			{
				string string4 = PlayerPrefs.GetString("MIS_" + text + "_TriggeredRules");
				string[] array7 = string4.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				string[] array8 = array7;
				foreach (string text5 in array8)
				{
					string[] array9 = text5.Split(':');
					if (array9.Length == 2)
					{
						triggeredRules[array9[0]] = array9[1] == "1";
					}
				}
			}
			if (PlayerPrefs.HasKey("MIS_" + text + "_TriggerCounts"))
			{
				string string5 = PlayerPrefs.GetString("MIS_" + text + "_TriggerCounts");
				string[] array10 = string5.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				string[] array11 = array10;
				foreach (string text6 in array11)
				{
					string[] array12 = text6.Split(':');
					if (array12.Length == 2 && int.TryParse(array12[1], out var result))
					{
						triggerCounts[array12[0]] = result;
					}
				}
			}
			currentCaseId = text2;
			string currentSaveFileName2 = GetCurrentSaveFileName();
			if (text != currentSaveFileName2)
			{
				Plugin.LogDebug("Migrating tracking data from " + text + " to " + currentSaveFileName2);
				SaveTrackingData();
				text = currentSaveFileName2;
			}
			Plugin.LogDebug("Loaded tracking data for save file: " + text + ", case ID: " + currentCaseId);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(29, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error loading tracking data: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
			ResetTracking();
		}
	}

	public void LoadConfig()
	{
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Expected O, but got Unknown
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Expected O, but got Unknown
		//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Expected O, but got Unknown
		//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d5: Expected O, but got Unknown
		Configs.Clear();
		if (!Directory.Exists(ConfigFolderPath))
		{
			Directory.CreateDirectory(ConfigFolderPath);
		}
		string pluginPath = Paths.PluginPath;
		List<string> list = new List<string>();
		string[] files = Directory.GetFiles(ConfigFolderPath, "*MIS.json");
		if (files.Length != 0)
		{
			list.AddRange(files);
		}
		else
		{
			string text = Path.Combine(ConfigFolderPath, "DefaultMIS.json");
			ModConfig modConfig = new ModConfig();
			modConfig.SaveToFile(text);
			list.Add(text);
			PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)"Created default configuration file: DefaultMIS.json");
		}
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val;
		try
		{
			string[] directories = Directory.GetDirectories(pluginPath, "*", SearchOption.AllDirectories);
			string[] array = directories;
			foreach (string text2 in array)
			{
				if (text2.Equals(ConfigFolderPath, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				string[] files2 = Directory.GetFiles(text2, "*MIS.json");
				if (files2.Length != 0)
				{
					list.AddRange(files2);
					ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
					val = new BepInExInfoLogInterpolatedStringHandler(32, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Found ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(files2.Length);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" additional config(s) in: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text2);
					}
					log.LogInfo(val);
				}
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log2 = PluginController<Plugin, IEmptyBindings>.Log;
			BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(34, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Error searching for config files: ");
				((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
			}
			log2.LogError(val2);
		}
		foreach (string item in list)
		{
			try
			{
				ModConfig modConfig2 = ModConfig.LoadFromFile(item);
				if (modConfig2 != null)
				{
					Configs.Add(modConfig2);
					ManualLogSource log3 = PluginController<Plugin, IEmptyBindings>.Log;
					val = new BepInExInfoLogInterpolatedStringHandler(39, 3, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded configuration from ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Path.GetFileName(Path.GetDirectoryName(item)));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("/");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(Path.GetFileName(item));
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" with ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(modConfig2.SpawnRules.Count);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" rules");
					}
					log3.LogInfo(val);
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log4 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(28, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Error loading config file ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(item);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex2.Message);
				}
				log4.LogError(val2);
			}
		}
		triggeredRules.Clear();
		foreach (ModConfig config in Configs)
		{
			foreach (SpawnRule spawnRule in config.SpawnRules)
			{
				triggeredRules[spawnRule.Name] = false;
			}
		}
		int num = 0;
		foreach (ModConfig config2 in Configs)
		{
			num += config2.SpawnRules.Count;
		}
		ManualLogSource log5 = PluginController<Plugin, IEmptyBindings>.Log;
		val = new BepInExInfoLogInterpolatedStringHandler(45, 2, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Loaded ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Configs.Count);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" configuration files with ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" total rules");
		}
		log5.LogInfo(val);
	}

	public void SaveConfig(ModConfig config, string fileName)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Expected O, but got Unknown
		string filePath = Path.Combine(ConfigFolderPath, fileName);
		config.SaveToFile(filePath);
		ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
		bool flag = default(bool);
		BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag);
		if (flag)
		{
			((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Configuration saved to ");
			((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(fileName);
		}
		log.LogInfo(val);
	}

	public void SaveDefaultConfig()
	{
		if (Configs.Count > 0)
		{
			SaveConfig(Configs[0], "DefaultMIS.json");
			return;
		}
		ModConfig config = new ModConfig();
		SaveConfig(config, "DefaultMIS.json");
	}

	public void CheckRulesForEvent(string eventName, string murderType)
	{
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Expected O, but got Unknown
		//IL_0793: Unknown result type (might be due to invalid IL or missing references)
		//IL_079a: Expected O, but got Unknown
		bool flag2 = default(bool);
		foreach (ModConfig config in Configs)
		{
			if (!config.Enabled)
			{
				continue;
			}
			foreach (SpawnRule item in config.SpawnRules.Where((SpawnRule r) => !r.RequiresPriorItem))
			{
				if (!item.Enabled)
				{
					continue;
				}
				if (item.OnlySpawnOnce && spawnedItems.ContainsKey(item.Name) && spawnedItems[item.Name])
				{
					Plugin.LogDebug($"Skipping rule '{item.Name}' for event '{eventName}' because the item has already been spawned (OnlySpawnOnce=true)");
					continue;
				}
				if (item.OnlySpawnOnce)
				{
					bool flag = false;
					foreach (string triggerEvent in item.TriggerEvents)
					{
						string key = item.Name + "_" + triggerEvent;
						if (triggeredRules.ContainsKey(key) && triggeredRules[key])
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						Plugin.LogDebug($"Skipping rule '{item.Name}' for event '{eventName}' because it has already been triggered (OnlySpawnOnce=true)");
						continue;
					}
				}
				if (!item.TriggerEvents.Contains(eventName) || (!string.IsNullOrEmpty(item.MurderMO) && !(item.MurderMO == murderType)))
				{
					continue;
				}
				if (config.ShowDebugMessages)
				{
					ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 3, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Rule '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item.Name);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' triggered by event '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(eventName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' with murder type '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(murderType);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'");
					}
					log.LogInfo(val);
				}
				bool flag3 = true;
				if (item.RequiresMultipleTriggers && item.RequiredTriggerCount > 1)
				{
					string key2 = item.Name + "_" + eventName;
					int num = 0;
					if (triggerCounts.ContainsKey(key2))
					{
						num = triggerCounts[key2];
					}
					num++;
					triggerCounts[key2] = num;
					if (num < item.RequiredTriggerCount)
					{
						Plugin.LogDebug($"Rule '{item.Name}' for event '{eventName}' has been triggered {num}/{item.RequiredTriggerCount} times");
						flag3 = false;
					}
					else
					{
						Plugin.LogDebug($"Rule '{item.Name}' for event '{eventName}' has reached required trigger count ({num}/{item.RequiredTriggerCount})");
					}
				}
				bool flag4 = false;
				if (flag3)
				{
					flag4 = SpawnItem(item, eventName);
				}
				if (!flag4)
				{
					continue;
				}
				string key3 = item.Name + "_" + eventName;
				triggeredRules[key3] = true;
				Plugin.LogDebug($"Rule '{item.Name}' marked as triggered for event '{eventName}'");
				if (!item.OnlySpawnOnce)
				{
					continue;
				}
				foreach (string triggerEvent2 in item.TriggerEvents)
				{
					if (!(triggerEvent2 == eventName))
					{
						string key4 = item.Name + "_" + triggerEvent2;
						triggeredRules[key4] = true;
						Plugin.LogDebug($"Rule '{item.Name}' marked as triggered for event '{triggerEvent2}' (due to OnlySpawnOnce=true)");
					}
				}
			}
			foreach (SpawnRule item2 in config.SpawnRules.Where((SpawnRule r) => r.RequiresPriorItem))
			{
				if (!item2.Enabled)
				{
					continue;
				}
				if (item2.OnlySpawnOnce)
				{
					bool flag5 = false;
					foreach (string triggerEvent3 in item2.TriggerEvents)
					{
						string key5 = item2.Name + "_" + triggerEvent3;
						if (triggeredRules.ContainsKey(key5) && triggeredRules[key5])
						{
							flag5 = true;
							break;
						}
					}
					if (flag5)
					{
						Plugin.LogDebug($"Skipping rule '{item2.Name}' for event '{eventName}' because it has already been triggered (OnlySpawnOnce=true)");
						continue;
					}
				}
				if (!item2.TriggerEvents.Contains(eventName) || (!string.IsNullOrEmpty(item2.MurderMO) && !(item2.MurderMO == murderType)))
				{
					continue;
				}
				if (config.ShowDebugMessages)
				{
					ManualLogSource log2 = PluginController<Plugin, IEmptyBindings>.Log;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 3, ref flag2);
					if (flag2)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Rule '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(item2.Name);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' triggered by event '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(eventName);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' with murder type '");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(murderType);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'");
					}
					log2.LogInfo(val);
				}
				bool flag6 = true;
				if (item2.RequiresMultipleTriggers && item2.RequiredTriggerCount > 1)
				{
					string key6 = item2.Name + "_" + eventName;
					int num2 = 0;
					if (triggerCounts.ContainsKey(key6))
					{
						num2 = triggerCounts[key6];
					}
					num2++;
					triggerCounts[key6] = num2;
					if (num2 < item2.RequiredTriggerCount)
					{
						Plugin.LogDebug($"Rule '{item2.Name}' for event '{eventName}' has been triggered {num2}/{item2.RequiredTriggerCount} times");
						flag6 = false;
					}
					else
					{
						Plugin.LogDebug($"Rule '{item2.Name}' for event '{eventName}' has reached required trigger count ({num2}/{item2.RequiredTriggerCount})");
					}
				}
				bool flag7 = false;
				if (flag6)
				{
					flag7 = SpawnItem(item2, eventName);
				}
				if (!flag7)
				{
					continue;
				}
				string key7 = item2.Name + "_" + eventName;
				triggeredRules[key7] = true;
				Plugin.LogDebug($"Rule '{item2.Name}' marked as triggered for event '{eventName}'");
				if (!item2.OnlySpawnOnce)
				{
					continue;
				}
				foreach (string triggerEvent4 in item2.TriggerEvents)
				{
					if (!(triggerEvent4 == eventName))
					{
						string key8 = item2.Name + "_" + triggerEvent4;
						triggeredRules[key8] = true;
						Plugin.LogDebug($"Rule '{item2.Name}' marked as triggered for event '{triggerEvent4}' (due to OnlySpawnOnce=true)");
					}
				}
			}
		}
	}

	private bool SpawnItem(SpawnRule rule, string eventName = "")
	{
		//IL_0e64: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e6b: Expected O, but got Unknown
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0254: Expected O, but got Unknown
		//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c0: Expected O, but got Unknown
		//IL_08e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_08eb: Expected O, but got Unknown
		//IL_0d07: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d0e: Expected O, but got Unknown
		//IL_0d8f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d96: Expected O, but got Unknown
		//IL_0dfc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e03: Expected O, but got Unknown
		//IL_0aaf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab6: Expected O, but got Unknown
		//IL_0b35: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b3c: Expected O, but got Unknown
		bool flag = default(bool);
		try
		{
			if (rule.OnlySpawnOnce && spawnedItems.ContainsKey(rule.Name) && spawnedItems[rule.Name])
			{
				Plugin.LogDebug("Skipping spawn for rule '" + rule.Name + "': Item has already been spawned once");
				return false;
			}
			if (rule.RequiresPriorItem && !string.IsNullOrEmpty(rule.RequiredPriorItem))
			{
				if (!spawnedItems.ContainsKey(rule.RequiredPriorItem) || !spawnedItems[rule.RequiredPriorItem])
				{
					Plugin.LogDebug($"Skipping spawn for rule '{rule.Name}': Required prior item '{rule.RequiredPriorItem}' has not been spawned yet");
					return false;
				}
				if (rule.RequiresSeparateTrigger && !string.IsNullOrEmpty(eventName) && itemSpawnEvents.ContainsKey(rule.RequiredPriorItem) && itemSpawnEvents[rule.RequiredPriorItem] == eventName)
				{
					Plugin.LogDebug($"Skipping spawn for rule '{rule.Name}': Required prior item '{rule.RequiredPriorItem}' was spawned in the same event ('{eventName}') and RequiresSeparateTrigger is true");
					return false;
				}
				Plugin.LogDebug($"Required prior item '{rule.RequiredPriorItem}' found, proceeding with spawn for rule '{rule.Name}'");
			}
			Human owner = GetOwner(rule.BelongsTo);
			if ((Object)(object)owner == (Object)null)
			{
				ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(51, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cannot spawn item for rule '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(rule.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': No valid owner found");
				}
				log.LogInfo(val);
				return false;
			}
			Human recipient = GetRecipient(rule.Recipient);
			if ((Object)(object)recipient == (Object)null)
			{
				ManualLogSource log2 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(55, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cannot spawn item for rule '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(rule.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': No valid recipient found");
				}
				log2.LogInfo(val);
				return false;
			}
			if (rule.UseTraits && rule.TraitModifiers != null && rule.TraitModifiers.Count > 0)
			{
				Plugin.LogDebug("Checking trait matching for rule '" + rule.Name + "'...");
				bool flag2 = true;
				foreach (TraitModifier traitModifier in rule.TraitModifiers)
				{
					Human val2 = null;
					switch (traitModifier.Who)
					{
					case BelongsTo.Murderer:
					{
						MurderController instance2 = MurderController.Instance;
						val2 = ((instance2 != null) ? instance2.currentMurderer : null);
						break;
					}
					case BelongsTo.Victim:
					{
						MurderController instance6 = MurderController.Instance;
						val2 = ((instance6 != null) ? instance6.currentVictim : null);
						break;
					}
					case BelongsTo.Player:
						val2 = (Human)(object)Player.Instance;
						break;
					case BelongsTo.MurdererDoctor:
					{
						MurderController instance3 = MurderController.Instance;
						if ((Object)(object)((instance3 != null) ? instance3.currentMurderer : null) != (Object)null)
						{
							val2 = MurderController.Instance.currentMurderer.GetDoctor();
						}
						break;
					}
					case BelongsTo.VictimDoctor:
					{
						MurderController instance4 = MurderController.Instance;
						if ((Object)(object)((instance4 != null) ? instance4.currentVictim : null) != (Object)null)
						{
							val2 = MurderController.Instance.currentVictim.GetDoctor();
						}
						break;
					}
					case BelongsTo.MurdererLandlord:
					{
						MurderController instance5 = MurderController.Instance;
						if ((Object)(object)((instance5 != null) ? instance5.currentMurderer : null) != (Object)null)
						{
							val2 = MurderController.Instance.currentMurderer.GetLandlord();
						}
						break;
					}
					case BelongsTo.VictimLandlord:
					{
						MurderController instance = MurderController.Instance;
						if ((Object)(object)((instance != null) ? instance.currentVictim : null) != (Object)null)
						{
							val2 = MurderController.Instance.currentVictim.GetLandlord();
						}
						break;
					}
					default:
						Plugin.LogDebug($"Unknown trait modifier Who value: {traitModifier.Who}");
						break;
					}
					if ((Object)(object)val2 == (Object)null)
					{
						Plugin.LogDebug($"Cannot check traits: Human not found for {traitModifier.Who}");
						flag2 = false;
						break;
					}
					if (!CheckTraitMatch(val2, traitModifier))
					{
						Plugin.LogDebug($"Trait matching failed for {traitModifier.Who}");
						flag2 = false;
						break;
					}
				}
				if (!flag2)
				{
					Plugin.LogDebug("Skipping spawn for rule '" + rule.Name + "': Trait matching failed");
					return false;
				}
				Plugin.LogDebug("All trait modifiers matched for rule '" + rule.Name + "', proceeding with spawn");
			}
			if (rule.UseJobModifiers && rule.JobModifiers != null && rule.JobModifiers.Count > 0)
			{
				Plugin.LogDebug("Checking job matching for rule '" + rule.Name + "'...");
				bool flag3 = true;
				foreach (JobModifier jobModifier in rule.JobModifiers)
				{
					Human val3 = null;
					switch (jobModifier.Who)
					{
					case BelongsTo.Murderer:
					{
						MurderController instance8 = MurderController.Instance;
						val3 = ((instance8 != null) ? instance8.currentMurderer : null);
						break;
					}
					case BelongsTo.Victim:
					{
						MurderController instance12 = MurderController.Instance;
						val3 = ((instance12 != null) ? instance12.currentVictim : null);
						break;
					}
					case BelongsTo.Player:
						val3 = (Human)(object)Player.Instance;
						break;
					case BelongsTo.MurdererDoctor:
					{
						MurderController instance9 = MurderController.Instance;
						if ((Object)(object)((instance9 != null) ? instance9.currentMurderer : null) != (Object)null)
						{
							val3 = MurderController.Instance.currentMurderer.GetDoctor();
						}
						break;
					}
					case BelongsTo.VictimDoctor:
					{
						MurderController instance10 = MurderController.Instance;
						if ((Object)(object)((instance10 != null) ? instance10.currentVictim : null) != (Object)null)
						{
							val3 = MurderController.Instance.currentVictim.GetDoctor();
						}
						break;
					}
					case BelongsTo.MurdererLandlord:
					{
						MurderController instance11 = MurderController.Instance;
						if ((Object)(object)((instance11 != null) ? instance11.currentMurderer : null) != (Object)null)
						{
							val3 = MurderController.Instance.currentMurderer.GetLandlord();
						}
						break;
					}
					case BelongsTo.VictimLandlord:
					{
						MurderController instance7 = MurderController.Instance;
						if ((Object)(object)((instance7 != null) ? instance7.currentVictim : null) != (Object)null)
						{
							val3 = MurderController.Instance.currentVictim.GetLandlord();
						}
						break;
					}
					default:
						Plugin.LogDebug($"Unknown job modifier Who value: {jobModifier.Who}");
						break;
					}
					if ((Object)(object)val3 == (Object)null)
					{
						Plugin.LogDebug($"Cannot check job: Human not found for {jobModifier.Who}");
						flag3 = false;
						break;
					}
					if (!CheckJobMatch(val3, jobModifier))
					{
						Plugin.LogDebug($"Job matching failed for {jobModifier.Who}");
						flag3 = false;
						break;
					}
				}
				if (!flag3)
				{
					Plugin.LogDebug("Skipping spawn for rule '" + rule.Name + "': Job matching failed");
					return false;
				}
				Plugin.LogDebug("All job modifiers matched for rule '" + rule.Name + "', proceeding with spawn");
			}
			Interactable spawnLocation = GetSpawnLocation(rule, owner, recipient);
			if (spawnLocation == null && rule.SpawnLocation == SpawnLocationType.Mailbox)
			{
				ManualLogSource log3 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(60, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Cannot spawn item for rule '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(rule.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("': No valid spawn location found");
				}
				log3.LogInfo(val);
				return false;
			}
			if (rule.SpawnLocation == SpawnLocationType.HomeBuildingEntrance)
			{
			}
			switch (rule.SpawnLocation)
			{
			case SpawnLocationType.Mailbox:
				SpawnItemMailbox.SpawnItemAtLocation(owner, recipient, spawnLocation, GetRandomItemToSpawn(rule), rule.UnlockMailbox, rule.SpawnChance);
				break;
			case SpawnLocationType.Doormat:
				SpawnItemDoormat.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.UseMultipleOwners, rule.Owners);
				break;
			case SpawnLocationType.HomeLobby:
				SpawnItemLobbyHome.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.UseMultipleOwners, rule.Owners);
				break;
			case SpawnLocationType.WorkplaceLobby:
				SpawnItemLobbyWork.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.SubLocationTypeBuildingEntrances, rule.UseMultipleOwners, rule.Owners);
				break;
			case SpawnLocationType.HomeBuildingEntrance:
				SpawnItemBuildingEntranceHome.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.SubLocationTypeBuildingEntrances);
				break;
			case SpawnLocationType.WorkplaceBuildingEntrance:
				SpawnItemBuildingEntranceWorkplace.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.SubLocationTypeBuildingEntrances);
				break;
			case SpawnLocationType.HotelRooftopBar:
				SpawnItemHotelRooftopBar.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.HotelRooftopBarSubLocations);
				break;
			case SpawnLocationType.Random:
			{
				if (rule.RandomSpawnLocations == null || rule.RandomSpawnLocations.Count == 0)
				{
					ManualLogSource log5 = PluginController<Plugin, IEmptyBindings>.Log;
					BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(93, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[ConfigManager] Random spawn location selected but no RandomSpawnLocations defined in rule '");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(rule.Name);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("'");
					}
					log5.LogWarning(val4);
					return false;
				}
				int index = Random.Range(0, rule.RandomSpawnLocations.Count);
				string text = rule.RandomSpawnLocations[index];
				if (!Enum.TryParse<SpawnLocationType>(text, out var result))
				{
					ManualLogSource log6 = PluginController<Plugin, IEmptyBindings>.Log;
					BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(58, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[ConfigManager] Invalid random location name '");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(text);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("' in rule '");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(rule.Name);
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("'");
					}
					log6.LogWarning(val4);
					return false;
				}
				SpawnRule rule2 = new SpawnRule
				{
					Name = rule.Name + "_Random",
					ItemsToSpawn = rule.ItemsToSpawn,
					BelongsTo = rule.BelongsTo,
					Recipient = rule.Recipient,
					SpawnLocation = result,
					SpawnChance = rule.SpawnChance,
					UnlockMailbox = rule.UnlockMailbox,
					SubLocationTypeBuildingEntrances = rule.SubLocationTypeBuildingEntrances
				};
				return SpawnItem(rule2);
			}
			case SpawnLocationType.CityHallBathroom:
				SpawnItemCityHallBathroom.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance);
				break;
			case SpawnLocationType.Custom:
				SpawnItemCustomBuilding.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.CustomRoomName, rule.CustomBuildingPreset, rule.CustomFloorNames, rule.CustomSubRoomName, rule.CustomRoomPreset, rule.CustomSubRoomPreset, rule.CustomRoomNames, rule.CustomRoomPresets, rule.CustomSubRoomNames, rule.CustomSubRoomPresets, rule.UseFurniture, rule.FurniturePresets);
				break;
			case SpawnLocationType.Home:
				SpawnItemHome.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.CustomRoomName, rule.UseFurniture, rule.FurniturePresets);
				break;
			case SpawnLocationType.Workplace:
				SpawnItemWork.SpawnItemAtLocation(owner, recipient, GetRandomItemToSpawn(rule), rule.SpawnChance, rule.CustomRoomName, rule.UseFurniture, rule.FurniturePresets, rule.UseMultipleOwners, rule.Owners);
				break;
			default:
			{
				ManualLogSource log4 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(52, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Using mailbox spawner for location type by default: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<SpawnLocationType>(rule.SpawnLocation);
				}
				log4.LogInfo(val);
				if (spawnLocation != null)
				{
					SpawnItemMailbox.SpawnItemAtLocation(owner, recipient, spawnLocation, GetRandomItemToSpawn(rule), rule.UnlockMailbox, rule.SpawnChance);
				}
				break;
			}
			}
			if (rule.OnlySpawnOnce)
			{
				spawnedItems[rule.Name] = true;
				ManualLogSource log7 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(56, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Marked item from rule '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(rule.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' as spawned (OnlySpawnOnce=true)");
				}
				log7.LogInfo(val);
			}
			if (!string.IsNullOrEmpty(eventName))
			{
				itemSpawnEvents[rule.Name] = eventName;
				ManualLogSource log8 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Item from rule '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(rule.Name);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' was spawned by event '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(eventName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("'");
				}
				log8.LogInfo(val);
			}
			return true;
		}
		catch (Exception ex)
		{
			ManualLogSource log9 = PluginController<Plugin, IEmptyBindings>.Log;
			BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(21, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("Error spawning item: ");
				((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ex.Message);
			}
			log9.LogError(val5);
			return false;
		}
	}

	private Human GetOwner(BelongsTo belongsTo)
	{
		return GetOwnerForFingerprint(belongsTo);
	}

	public Human GetOwnerForFingerprint(BelongsTo belongsTo)
	{
		switch (belongsTo)
		{
		case BelongsTo.Murderer:
			return MurderController.Instance.currentMurderer;
		case BelongsTo.Victim:
			return MurderController.Instance.currentVictim;
		case BelongsTo.Player:
			return (Human)(object)Player.Instance;
		case BelongsTo.MurdererDoctor:
			return MurderController.Instance.currentMurderer.GetDoctor();
		case BelongsTo.VictimDoctor:
			return MurderController.Instance.currentVictim.GetDoctor();
		case BelongsTo.MurdererLandlord:
			return MurderController.Instance.currentMurderer.GetLandlord();
		case BelongsTo.VictimLandlord:
			return MurderController.Instance.currentVictim.GetLandlord();
		case BelongsTo.Random:
			if (Random.Range(0f, 1f) > 0.5f)
			{
				return MurderController.Instance.currentMurderer;
			}
			return MurderController.Instance.currentVictim;
		default:
			return MurderController.Instance.currentMurderer;
		}
	}

	private Human GetRecipient(Recipient recipient)
	{
		switch (recipient)
		{
		case Recipient.Murderer:
			return MurderController.Instance.currentMurderer;
		case Recipient.Victim:
			return MurderController.Instance.currentVictim;
		case Recipient.Player:
			return (Human)(object)Player.Instance;
		case Recipient.MurdererDoctor:
			return MurderController.Instance.currentMurderer.GetDoctor();
		case Recipient.VictimDoctor:
			return MurderController.Instance.currentVictim.GetDoctor();
		case Recipient.MurdererLandlord:
			return MurderController.Instance.currentMurderer.GetLandlord();
		case Recipient.VictimLandlord:
			return MurderController.Instance.currentVictim.GetLandlord();
		case Recipient.Random:
			if (Random.Range(0f, 1f) > 0.5f)
			{
				return MurderController.Instance.currentMurderer;
			}
			return MurderController.Instance.currentVictim;
		default:
			return MurderController.Instance.currentMurderer;
		}
	}

	private Interactable GetSpawnLocation(SpawnRule rule, Human belongsTo, Human recipient)
	{
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		switch (rule.SpawnLocation)
		{
		case SpawnLocationType.Mailbox:
			return Toolbox.Instance.GetMailbox(recipient);
		case SpawnLocationType.Doormat:
		{
			if ((Object)(object)recipient != (Object)null && (Object)(object)recipient.home != (Object)null)
			{
				return null;
			}
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(84, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[ConfigManager] Cannot spawn item in doormat: Recipient or home address is null for ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((recipient != null) ? ((Object)recipient).name : null);
			}
			log.LogWarning(val);
			return null;
		}
		case SpawnLocationType.HomeLobby:
			if ((Object)(object)recipient != (Object)null && (Object)(object)recipient.home != (Object)null)
			{
				return null;
			}
			return null;
		case SpawnLocationType.HomeBuildingEntrance:
			if ((Object)(object)recipient != (Object)null && (Object)(object)recipient.home != (Object)null)
			{
				return null;
			}
			return null;
		case SpawnLocationType.WorkplaceBuildingEntrance:
			if ((Object)(object)belongsTo != (Object)null && belongsTo.job != null && belongsTo.job.employer != null && (Object)(object)belongsTo.job.employer.address != (Object)null)
			{
				return null;
			}
			return null;
		case SpawnLocationType.CityHallBathroom:
			if ((Object)(object)belongsTo != (Object)null)
			{
				return null;
			}
			return null;
		case SpawnLocationType.HotelRooftopBar:
			if ((Object)(object)belongsTo != (Object)null)
			{
				return null;
			}
			return null;
		case SpawnLocationType.Random:
			return null;
		default:
			return null;
		}
	}

	public void ResetTriggeredRules()
	{
		triggeredRules.Clear();
		foreach (ModConfig config in Configs)
		{
			foreach (SpawnRule spawnRule in config.SpawnRules)
			{
				triggeredRules[spawnRule.Name] = false;
			}
		}
	}

	private bool CheckTraitMatch(Human human, TraitModifier traitModifier)
	{
		if ((Object)(object)human == (Object)null || human.characterTraits == null || human.characterTraits.Count == 0)
		{
			Plugin.LogDebug("Cannot check traits: Human is null or has no traits");
			return false;
		}
		Plugin.LogDebug("Checking traits for " + ((Object)human).name + ":");
		Enumerator<Trait> enumerator = human.characterTraits.GetEnumerator();
		while (enumerator.MoveNext())
		{
			Trait current = enumerator.Current;
			if (current != null)
			{
				Plugin.LogDebug("- " + current.name);
			}
		}
		List<string> list = new List<string>();
		Enumerator<Trait> enumerator2 = human.characterTraits.GetEnumerator();
		while (enumerator2.MoveNext())
		{
			Trait current2 = enumerator2.Current;
			if (current2 != null)
			{
				list.Add(current2.name);
			}
		}
		if (traitModifier.Rule == TraitRule.IfAnyOfThese)
		{
			foreach (string trait in traitModifier.TraitList)
			{
				if (list.Contains(trait))
				{
					Plugin.LogDebug("Found matching trait: " + trait);
					return true;
				}
			}
			Plugin.LogDebug("No matching traits found for IfAnyOfThese rule");
			return false;
		}
		if (traitModifier.Rule == TraitRule.IfAllOfThese)
		{
			foreach (string trait2 in traitModifier.TraitList)
			{
				if (!list.Contains(trait2))
				{
					Plugin.LogDebug("Missing required trait: " + trait2);
					return false;
				}
			}
			Plugin.LogDebug("All required traits found for IfAllOfThese rule");
			return true;
		}
		if (traitModifier.Rule == TraitRule.IfNoneOfThese)
		{
			foreach (string trait3 in traitModifier.TraitList)
			{
				if (list.Contains(trait3))
				{
					Plugin.LogDebug("Found excluded trait: " + trait3);
					return false;
				}
			}
			Plugin.LogDebug("No excluded traits found for IfNoneOfThese rule");
			return true;
		}
		Plugin.LogDebug($"Unknown trait rule: {traitModifier.Rule}");
		return false;
	}

	private string GetRandomItemToSpawn(SpawnRule rule)
	{
		if (rule == null || rule.ItemsToSpawn == null || rule.ItemsToSpawn.Count == 0)
		{
			return string.Empty;
		}
		if (rule.ItemsToSpawn.Count == 1)
		{
			return rule.ItemsToSpawn[0];
		}
		int index = Random.Range(0, rule.ItemsToSpawn.Count);
		string text = rule.ItemsToSpawn[index];
		Plugin.LogDebug($"Randomly selected item '{text}' from {rule.ItemsToSpawn.Count} possible items for rule '{rule.Name}'");
		return text;
	}

	private bool CheckJobMatch(Human human, JobModifier jobModifier)
	{
		if ((Object)(object)human == (Object)null || human.job == null)
		{
			Plugin.LogDebug("Cannot check job: Human is null or has no job");
			return false;
		}
		string name = human.job.name;
		string text = (((SoCustomComparison)(object)human.job.preset != (SoCustomComparison)null) ? ((Object)human.job.preset).name : "");
		Plugin.LogDebug("Checking job for " + ((Object)human).name + ":");
		Plugin.LogDebug("- Job name: " + name);
		Plugin.LogDebug("- Job preset name: " + text);
		if (jobModifier.Rule == JobRule.IfAnyOfThese)
		{
			foreach (string job in jobModifier.JobList)
			{
				if (name == job || text == job)
				{
					Plugin.LogDebug("Found matching job: " + job);
					return true;
				}
			}
			Plugin.LogDebug("No matching jobs found for IfAnyOfThese rule");
			return false;
		}
		if (jobModifier.Rule == JobRule.IfNoneOfThese)
		{
			foreach (string job2 in jobModifier.JobList)
			{
				if (name == job2 || text == job2)
				{
					Plugin.LogDebug("Found excluded job: " + job2);
					return false;
				}
			}
			Plugin.LogDebug("No excluded jobs found for IfNoneOfThese rule");
			return true;
		}
		Plugin.LogDebug($"Unknown job rule: {jobModifier.Rule}");
		return false;
	}
}
public static class CoroutineHelper
{
	public static void StartCoroutine(IEnumerator routine)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		try
		{
			RuntimeHelper.StartCoroutine(routine);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(26, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error starting coroutine: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}

	public static IEnumerator WaitForSeconds(float seconds)
	{
		float startTime = Time.time;
		while (Time.time - startTime < seconds)
		{
			yield return null;
		}
	}

	public static IEnumerator DelayedAction(float seconds, Action action)
	{
		yield return WaitForSeconds(seconds);
		action?.Invoke();
	}
}
public class ModConfig
{
	public static ModConfig Instance { get; set; }

	public bool Enabled { get; set; } = true;


	public bool ShowDebugMessages { get; set; } = true;


	public List<SpawnRule> SpawnRules { get; set; } = new List<SpawnRule>();


	public ModConfig()
	{
		SpawnRules.Add(new SpawnRule
		{
			Name = "Default Pencil in Mailbox",
			Enabled = true,
			MurderMO = "ExampleMO",
			TriggerEvents = new List<string> { "OnVictimKilled" },
			ItemToSpawn = "Pencil",
			SpawnLocation = SpawnLocationType.Mailbox,
			BelongsTo = BelongsTo.Murderer,
			Recipient = Recipient.Victim,
			SpawnChance = 1f,
			UnlockMailbox = true,
			SubLocationTypeBuildingEntrances = SubLocationTypeBuildingEntrances.Inside,
			RandomSpawnLocations = new List<string> { "Doormat", "Lobby", "BuildingEntrance", "WorkplaceBuildingEntrance" },
			HotelRooftopBarSubLocations = new List<string> { "RooftopBar", "BarDiningRoom" }
		});
	}

	public void SaveToFile(string filePath)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Expected O, but got Unknown
		try
		{
			JsonSerializerOptions options = new JsonSerializerOptions
			{
				WriteIndented = true
			};
			string contents = JsonSerializer.Serialize(this, options);
			File.WriteAllText(filePath, contents);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to save configuration: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}

	public static ModConfig LoadFromFile(string filePath)
	{
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		try
		{
			if (File.Exists(filePath))
			{
				string json = File.ReadAllText(filePath);
				return JsonSerializer.Deserialize<ModConfig>(json);
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Failed to load configuration: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
		return new ModConfig();
	}
}
[Serializable]
public class Vector3Serializable
{
	public float X { get; set; }

	public float Y { get; set; }

	public float Z { get; set; }

	public Vector3Serializable()
	{
	}

	public Vector3Serializable(float x, float y, float z)
	{
		X = x;
		Y = y;
		Z = z;
	}

	public Vector3 ToVector3()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3(X, Y, Z);
	}

	public static Vector3Serializable FromVector3(Vector3 vector)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		return new Vector3Serializable(vector.x, vector.y, vector.z);
	}
}
public enum SpawnLocationType
{
	Mailbox,
	Doormat,
	HomeLobby,
	WorkplaceLobby,
	HomeBuildingEntrance,
	WorkplaceBuildingEntrance,
	CityHallBathroom,
	HotelRooftopBar,
	Home,
	Workplace,
	Random,
	Custom
}
public enum SubLocationTypeBuildingEntrances
{
	Inside,
	Outside
}
public enum BelongsTo
{
	Murderer,
	Victim,
	Player,
	MurdererDoctor,
	VictimDoctor,
	MurdererLandlord,
	VictimLandlord,
	Random
}
public enum Recipient
{
	Murderer,
	Victim,
	Player,
	MurdererDoctor,
	VictimDoctor,
	MurdererLandlord,
	VictimLandlord,
	Random
}
public enum TraitRule
{
	IfAnyOfThese,
	IfAllOfThese,
	IfNoneOfThese
}
public enum JobRule
{
	IfAnyOfThese,
	IfNoneOfThese
}
[Serializable]
public class TraitModifier
{
	public BelongsTo Who { get; set; } = BelongsTo.Victim;


	public TraitRule Rule { get; set; } = TraitRule.IfAnyOfThese;


	public List<string> TraitList { get; set; } = new List<string>();

}
[Serializable]
public class JobModifier
{
	public BelongsTo Who { get; set; } = BelongsTo.Victim;


	public JobRule Rule { get; set; } = JobRule.IfAnyOfThese;


	public List<string> JobList { get; set; } = new List<string>();

}
[Serializable]
public class SpawnRule
{
	public string Name { get; set; } = "Unnamed Rule";


	public bool Enabled { get; set; } = true;


	public List<string> TriggerEvents { get; set; } = new List<string>();


	public string MurderMO { get; set; } = "ExampleMO";


	public List<string> ItemsToSpawn { get; set; } = new List<string> { "Pencil" };


	public string ItemToSpawn
	{
		get
		{
			if (ItemsToSpawn == null || ItemsToSpawn.Count == 0)
			{
				return "Pencil";
			}
			return ItemsToSpawn[0];
		}
		set
		{
			if (ItemsToSpawn == null)
			{
				ItemsToSpawn = new List<string>();
			}
			ItemsToSpawn.Clear();
			if (!string.IsNullOrEmpty(value))
			{
				ItemsToSpawn.Add(value);
			}
		}
	}

	public SpawnLocationType SpawnLocation { get; set; } = SpawnLocationType.Mailbox;


	public BelongsTo BelongsTo { get; set; } = BelongsTo.Murderer;


	public Recipient Recipient { get; set; } = Recipient.Murderer;


	public int SpawnCount { get; set; } = 1;


	public float SpawnChance { get; set; } = 1f;


	public bool UnlockMailbox { get; set; } = true;


	public SubLocationTypeBuildingEntrances SubLocationTypeBuildingEntrances { get; set; } = SubLocationTypeBuildingEntrances.Inside;


	public List<string> RandomSpawnLocations { get; set; } = new List<string>();


	public List<string> HotelRooftopBarSubLocations { get; set; } = new List<string>();


	public string CustomBuildingPreset { get; set; } = "";


	public string CustomRoomName { get; set; } = "";


	public string CustomRoomPreset { get; set; } = "";


	public string CustomSubRoomName { get; set; } = "";


	public string CustomSubRoomPreset { get; set; } = "";


	public List<string> CustomRoomNames { get; set; } = new List<string>();


	public List<string> CustomRoomPresets { get; set; } = new List<string>();


	public List<string> CustomSubRoomNames { get; set; } = new List<string>();


	public List<string> CustomSubRoomPresets { get; set; } = new List<string>();


	public List<string> CustomFloorNames { get; set; } = new List<string>();


	public bool UseFurniture { get; set; } = false;


	public List<string> FurniturePresets { get; set; } = new List<string>();


	public bool UseMultipleOwners { get; set; } = false;


	public List<BelongsTo> Owners { get; set; } = new List<BelongsTo>();


	public bool OnlySpawnOnce { get; set; } = false;


	public bool RequiresPriorItem { get; set; } = false;


	public string RequiredPriorItem { get; set; } = "";


	public bool RequiresSeparateTrigger { get; set; } = true;


	public bool RequiresMultipleTriggers { get; set; } = false;


	public int RequiredTriggerCount { get; set; } = 1;


	public bool UseTraits { get; set; } = false;


	public List<TraitModifier> TraitModifiers { get; set; } = new List<TraitModifier>();


	public bool UseJobModifiers { get; set; } = false;


	public List<JobModifier> JobModifiers { get; set; } = new List<JobModifier>();

}
[HarmonyPatch(typeof(MurderController), "OnVictimKilled")]
public class OnVictimKilledPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("OnVictimKilled", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(30, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in OnVictimKilledPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "PickNewVictim")]
public class PickNewVictimPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("PickNewVictim", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(29, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in PickNewVictimPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "OnVictimDiscovery")]
public class OnVictimDiscoveryPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("OnVictimDiscovery", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in OnVictimDiscoveryPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "TriggerCoverUpTelephoneCall")]
public class TriggerCoverUpTelephoneCallPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("TriggerCoverUpTelephoneCall", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(43, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in TriggerCoverUpTelephoneCallPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "OnCoverUpAccept")]
public class OnCoverUpAcceptPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("OnCoverUpAccept", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(31, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in OnCoverUpAcceptPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "OnCoverUpReject")]
public class OnCoverUpRejectPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("OnCoverUpReject", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(31, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in OnCoverUpRejectPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "TriggerKidnappingCase")]
public class TriggerKidnappingCasePatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("TriggerKidnappingCase", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(37, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in TriggerKidnappingCasePatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "TriggerRansomDelivery")]
public class TriggerRansomDeliveryPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("TriggerRansomDelivery", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(37, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in TriggerRansomDeliveryPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "KidnapperCollectsRansom")]
public class KidnapperCollectsRansomPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("KidnapperCollectsRansom", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(39, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in KidnapperCollectsRansomPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "KidnapperCollectedRansom")]
public class KidnapperCollectedRansomPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("KidnapperCollectedRansom", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in KidnapperCollectedRansomPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "TriggerRansomFail")]
public class TriggerRansomFailPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("TriggerRansomFail", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in TriggerRansomFailPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "VictimFreed")]
public class VictimFreedPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("VictimFreed", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in VictimFreedPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "OnCaseSolved")]
public class OnCaseSolvedPatch
{
	public static void Postfix()
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("OnCaseSolved", murderType);
			ConfigManager.Instance.ResetTracking();
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(28, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in OnCaseSolvedPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "CitizenHasSeenBody", new Type[]
{
	typeof(Human),
	typeof(Human)
})]
public class CitizenHasSeenBodyPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("CitizenHasSeenBody", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(34, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in CitizenHasSeenBodyPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "CoverUpFailCheck", new Type[] { typeof(Human) })]
public class CoverUpFailCheckPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("CoverUpFailCheck", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(32, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in CoverUpFailCheckPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[HarmonyPatch(typeof(MurderController), "TriggerSuccessfulCoverUp", new Type[] { typeof(Evidence) })]
public class TriggerSuccessfulCoverUpPatch
{
	public static void Postfix()
	{
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Expected O, but got Unknown
		try
		{
			string murderType = "";
			if ((Object)(object)MurderController.Instance != (Object)null && (SoCustomComparison)(object)MurderController.Instance.chosenMO != (SoCustomComparison)null)
			{
				murderType = ((Object)MurderController.Instance.chosenMO).name;
			}
			ConfigManager.Instance.CheckRulesForEvent("TriggerSuccessfulCoverUp", murderType);
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(40, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in TriggerSuccessfulCoverUpPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
[BepInPlugin("ShaneeexD.MurderItemSpawner", "MurderItemSpawner", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : PluginController<Plugin>
{
	public const string PLUGIN_GUID = "ShaneeexD.MurderItemSpawner";

	public const string PLUGIN_NAME = "MurderItemSpawner";

	public const string PLUGIN_VERSION = "1.0.0";

	public static ConfigEntry<bool> showDebugLogs;

	public override void Load()
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		((PluginController<Plugin, IEmptyBindings>)(object)this).Harmony.PatchAll(Assembly.GetExecutingAssembly());
		SaveGamerHandlers saveGamerHandlers = new SaveGamerHandlers();
		PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)"MurderItemSpawner plugin is patched.");
		showDebugLogs = base.Config.Bind<bool>("General", "ShowDebugLogs", false, new ConfigDescription("Show debug logs.", (AcceptableValueBase)null, Array.Empty<object>()));
	}

	public static void LogDebug(string message)
	{
		if (showDebugLogs != null && showDebugLogs.Value)
		{
			PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)message);
		}
	}
}
[HarmonyPatch(typeof(SessionData))]
[HarmonyPatch("PauseGame")]
public class PauseManager
{
	public static void Prefix(ref bool showPauseText, ref bool delayOverride, ref bool openDesktopMode)
	{
	}
}
[HarmonyPatch(typeof(SessionData))]
[HarmonyPatch("ResumeGame")]
public class ResumeGameManager
{
	public static void Prefix()
	{
	}
}
[Serializable]
public class MurderItemSpawnerSaveData
{
	public List<SavedItem> SpawnedItems = new List<SavedItem>();

	public List<SavedItemEvent> ItemSpawnEvents = new List<SavedItemEvent>();

	public List<SavedTriggeredRule> TriggeredRules = new List<SavedTriggeredRule>();

	public string CurrentCaseId = "";

	public void SetFromDictionaries(Dictionary<string, bool> spawnedItems, Dictionary<string, string> itemSpawnEvents, Dictionary<string, bool> triggeredRules, string caseId)
	{
		SpawnedItems.Clear();
		foreach (KeyValuePair<string, bool> spawnedItem in spawnedItems)
		{
			SpawnedItems.Add(new SavedItem
			{
				RuleName = spawnedItem.Key,
				IsSpawned = spawnedItem.Value
			});
		}
		ItemSpawnEvents.Clear();
		foreach (KeyValuePair<string, string> itemSpawnEvent in itemSpawnEvents)
		{
			ItemSpawnEvents.Add(new SavedItemEvent
			{
				RuleName = itemSpawnEvent.Key,
				EventName = itemSpawnEvent.Value
			});
		}
		TriggeredRules.Clear();
		foreach (KeyValuePair<string, bool> triggeredRule in triggeredRules)
		{
			TriggeredRules.Add(new SavedTriggeredRule
			{
				RuleEventKey = triggeredRule.Key,
				IsTriggered = triggeredRule.Value
			});
		}
		CurrentCaseId = caseId;
	}

	public void GetDictionaries(out Dictionary<string, bool> spawnedItems, out Dictionary<string, string> itemSpawnEvents, out Dictionary<string, bool> triggeredRules, out string caseId)
	{
		spawnedItems = new Dictionary<string, bool>();
		foreach (SavedItem spawnedItem in SpawnedItems)
		{
			spawnedItems[spawnedItem.RuleName] = spawnedItem.IsSpawned;
		}
		itemSpawnEvents = new Dictionary<string, string>();
		foreach (SavedItemEvent itemSpawnEvent in ItemSpawnEvents)
		{
			itemSpawnEvents[itemSpawnEvent.RuleName] = itemSpawnEvent.EventName;
		}
		triggeredRules = new Dictionary<string, bool>();
		foreach (SavedTriggeredRule triggeredRule in TriggeredRules)
		{
			triggeredRules[triggeredRule.RuleEventKey] = triggeredRule.IsTriggered;
		}
		caseId = CurrentCaseId;
	}
}
[Serializable]
public class SavedItem
{
	public string RuleName;

	public bool IsSpawned;
}
[Serializable]
public class SavedItemEvent
{
	public string RuleName;

	public string EventName;
}
[Serializable]
public class SavedTriggeredRule
{
	public string RuleEventKey;

	public bool IsTriggered;
}
public class SaveGamerHandlers : MonoBehaviour
{
	public SaveGamerHandlers()
	{
		Lib.SaveGame.OnAfterLoad += HandleGameLoaded;
		Lib.SaveGame.OnAfterNewGame += HandleNewGameStarted;
		Lib.SaveGame.OnBeforeNewGame += HandleGameBeforeNewGame;
		Lib.SaveGame.OnBeforeLoad += HandleGameBeforeLoad;
		Lib.SaveGame.OnBeforeDelete += HandleGameBeforeDelete;
		Lib.SaveGame.OnAfterDelete += HandleGameAfterDelete;
		Lib.SaveGame.OnAfterSave += HandleGameSaved;
	}

	private void HandleNewGameStarted(object sender, EventArgs e)
	{
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected O, but got Unknown
		try
		{
			PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)"[HandleNewGameStarted] New game started, resetting configuration");
			ConfigManager.Instance.ResetTriggeredRules();
			ConfigManager.Instance.ResetTracking();
			ConfigManager.Instance.LoadConfig();
			ConfigManager.Instance.SaveTrackingData();
			PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)"[HandleNewGameStarted] New game tracking data initialized");
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(31, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in HandleNewGameStarted: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}

	private void HandleGameLoaded(object sender, EventArgs e)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		try
		{
			ConfigManager.Instance.LoadConfig();
			ConfigManager.Instance.LoadTrackingData();
			PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)"[HandleGameLoaded] Game loaded, tracking data loaded");
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in HandleGameLoaded: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}

	private void HandleGameBeforeNewGame(object sender, EventArgs e)
	{
	}

	private void HandleGameBeforeLoad(object sender, EventArgs e)
	{
	}

	private void HandleGameBeforeDelete(object sender, EventArgs e)
	{
	}

	private void HandleGameAfterDelete(object sender, EventArgs e)
	{
	}

	private void HandleGameSaved(object sender, EventArgs e)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		try
		{
			ConfigManager.Instance.SaveTrackingData();
			PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)"[HandleGameSaved] Game saved, tracking data saved");
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(26, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in HandleGameSaved: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}

	private void HandleConfig(object sender, EventArgs e)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Expected O, but got Unknown
		try
		{
			PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)"[HandleConfig] New game started, resetting configuration");
			ConfigManager.Instance.ResetTriggeredRules();
			ConfigManager.Instance.LoadConfig();
		}
		catch (Exception ex)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			bool flag = default(bool);
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(25, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Error in GameStartPatch: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log.LogError(val);
		}
	}
}
public class SpawnItemBuildingEntranceHome : MonoBehaviour
{
	private static SpawnItemBuildingEntranceHome _instance;

	private static Vector3 spawnPosition;

	private static SpawnItemBuildingEntranceHome Instance
	{
		get
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			if ((Object)(object)_instance == (Object)null)
			{
				GameObject val = new GameObject("SpawnItemBuildingEntranceHome_Instance");
				Object.DontDestroyOnLoad((Object)(object)val);
				_instance = val.AddComponent<SpawnItemBuildingEntranceHome>();
			}
			return _instance;
		}
	}

	public static void SpawnItemAtLocation(Human owner, Human recipient, string presetName, float spawnChance, SubLocationTypeBuildingEntrances subLocationTypeBuildingEntrances, bool useMultipleOwners = false, List<BelongsTo> owners = null)
	{
		//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b9: Expected O, but got Unknown
		//IL_0405: Unknown result type (might be due to invalid IL or missing references)
		//IL_040c: Expected O, but got Unknown
		//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Expected O, but got Unknown
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Expected O, but got Unknown
		//IL_0364: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Expected O, but got Unknown
		//IL_033c: Unknown result type (might be due to invalid IL or missing references)
		bool flag = default(bool);
		try
		{
			float num = Random.Range(0f, 1f);
			if (num > spawnChance)
			{
				Plugin.LogDebug($"[SpawnItemBuildingEntrance] Skipping spawn of {presetName} due to chance (roll: {num}, needed: <= {spawnChance})");
				return;
			}
			InteractablePreset interactablePreset = Toolbox.Instance.GetInteractablePreset(presetName);
			if ((SoCustomComparison)(object)interactablePreset == (SoCustomComparison)null)
			{
				ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(73, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] Could not find interactable preset with name ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(presetName);
				}
				log.LogError(val);
				return;
			}
			if ((Object)(object)recipient == (Object)null || (Object)(object)recipient.home == (Object)null)
			{
				ManualLogSource log2 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(73, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[SpawnItemBuildingEntrance] Recipient has no valid address. Cannot spawn ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(presetName);
				}
				log2.LogWarning(val2);
				return;
			}
			NewAddress home = recipient.home;
			Plugin.LogDebug($"[SpawnItemBuildingEntrance] Owner: {((Object)owner).name}, Recipient: {((Object)recipient).name}, Address: {((Object)home).name}");
			Interactable val3 = SpawnItemAtBuildingEntrance(home, interactablePreset, owner, recipient, presetName, spawnChance, subLocationTypeBuildingEntrances);
			if (val3 != null)
			{
				if (useMultipleOwners && owners != null && owners.Count > 0)
				{
					val3.SetOwner(owner, true);
					foreach (BelongsTo owner2 in owners)
					{
						Human ownerForFingerprint = ConfigManager.Instance.GetOwnerForFingerprint(owner2);
						if ((Object)(object)ownerForFingerprint != (Object)null)
						{
							Plugin.LogDebug($"[SpawnItemBuildingEntrance] Adding fingerprint for {owner2}");
							val3.AddNewDynamicFingerprint(ownerForFingerprint, (PrintLife)0);
						}
						else
						{
							Plugin.LogDebug($"[SpawnItemBuildingEntrance] Could not add fingerprint for {owner2} - Human not found");
						}
					}
					Plugin.LogDebug("[SpawnItemBuildingEntrance] Successfully added multiple owners to '" + presetName + "'");
				}
				else
				{
					val3.SetOwner(owner, true);
				}
				Plugin.LogDebug("[SpawnItemBuildingEntrance] Successfully spawned '" + presetName + "' at building entrance. Item node: " + ((val3.node != null) ? ((Object)val3.node).ToString() : "null"));
				Plugin.LogDebug($"[SpawnItemBuildingEntrance] Item '{presetName}' final world position: {val3.wPos}");
			}
			else
			{
				ManualLogSource log3 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(74, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] Failed to create item '");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(presetName);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' at building entrance.");
				}
				log3.LogError(val);
			}
		}
		catch (Exception ex)
		{
			ManualLogSource log4 = PluginController<Plugin, IEmptyBindings>.Log;
			BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(50, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] Error spawning item ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(presetName);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
			}
			log4.LogError(val);
			ManualLogSource log5 = PluginController<Plugin, IEmptyBindings>.Log;
			val = new BepInExErrorLogInterpolatedStringHandler(41, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] Stack trace: ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.StackTrace);
			}
			log5.LogError(val);
		}
	}

	private static Interactable SpawnItemAtBuildingEntrance(NewAddress address, InteractablePreset itemPreset, Human owner, Human recipient, string itemNameForLog, float spawnChance, SubLocationTypeBuildingEntrances subLocationTypeBuildingEntrances)
	{
		//IL_0a1e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a25: Expected O, but got Unknown
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Expected O, but got Unknown
		//IL_0a5b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a62: Expected O, but got Unknown
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Expected O, but got Unknown
		//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0502: Expected O, but got Unknown
		//IL_0374: Unknown result type (might be due to invalid IL or missing references)
		//IL_037b: Expected O, but got Unknown
		//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c1: Expected O, but got Unknown
		//IL_06cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0703: Unknown result type (might be due to invalid IL or missing references)
		//IL_0708: Unknown result type (might be due to invalid IL or missing references)
		//IL_0710: Unknown result type (might be due to invalid IL or missing references)
		//IL_0716: Unknown result type (might be due to invalid IL or missing references)
		//IL_071b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0720: Unknown result type (might be due to invalid IL or missing references)
		//IL_0724: Unknown result type (might be due to invalid IL or missing references)
		//IL_0729: Unknown result type (might be due to invalid IL or missing references)
		//IL_072b: Unknown result type (might be due to invalid IL or missing references)
		//IL_072d: Unknown result type (might be due to invalid IL or missing references)
		//IL_067d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0684: Expected O, but got Unknown
		//IL_073e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0743: Unknown result type (might be due to invalid IL or missing references)
		//IL_0759: Unknown result type (might be due to invalid IL or missing references)
		//IL_075b: Unknown result type (might be due to invalid IL or missing references)
		//IL_075f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0764: Unknown result type (might be due to invalid IL or missing references)
		//IL_0769: Unknown result type (might be due to invalid IL or missing references)
		//IL_084d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0864: Unknown result type (might be due to invalid IL or missing references)
		//IL_0892: Unknown result type (might be due to invalid IL or missing references)
		//IL_08c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_08cb: Expected O, but got Unknown
		//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_07dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_090a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0928: Unknown result type (might be due to invalid IL or missing references)
		//IL_092d: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_09ec: Expected O, but got Unknown
		//IL_095a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0986: Unknown result type (might be due to invalid IL or missing references)
		bool flag = default(bool);
		if ((Object)(object)address == (Object)null)
		{
			ManualLogSource log = PluginController<Plugin, IEmptyBindings>.Log;
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(49, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] Address is null for ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(itemNameForLog);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(".");
			}
			log.LogWarning(val);
			return null;
		}
		NewBuilding building = ((NewGameLocation)address).building;
		if ((Object)(object)building != (Object)null)
		{
			Plugin.LogDebug("[SpawnItemBuildingEntrance] Found building directly from address: " + ((Object)building).name);
		}
		else
		{
			Plugin.LogDebug("[SpawnItemBuildingEntrance] No building found directly from address, trying floor");
			if (!((Object)(object)((NewGameLocation)address).floor != (Object)null))
			{
				ManualLogSource log2 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(61, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] Could not find floor for address ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)address).name);
				}
				log2.LogWarning(val);
				return null;
			}
			Plugin.LogDebug("[SpawnItemBuildingEntrance] Found floor for address " + ((Object)address).name);
		}
		NewWall val2 = null;
		NewWall val3 = null;
		if ((Object)(object)building != (Object)null && building.mainEntrance != null)
		{
			val3 = building.mainEntrance;
			Plugin.LogDebug("[SpawnItemBuildingEntrance] Found main entrance directly from building");
		}
		else if ((Object)(object)building != (Object)null && building.additionalEntrances != null && building.additionalEntrances.Count > 0)
		{
			Plugin.LogDebug($"[SpawnItemBuildingEntrance] Checking {building.additionalEntrances.Count} additional entrances from building");
			Enumerator<NewWall> enumerator = building.additionalEntrances.GetEnumerator();
			while (enumerator.MoveNext())
			{
				NewWall current = enumerator.Current;
				if (current != null)
				{
					NewNode node = current.otherWall.node;
					if (node != null && (Object)(object)node.gameLocation != (Object)null && (Object)(object)node.gameLocation.thisAsStreet != (Object)null)
					{
						val3 = current;
						Plugin.LogDebug("[SpawnItemBuildingEntrance] Found street entrance in building's additional entrances");
						break;
					}
				}
			}
		}
		if (val3 == null && (Object)(object)((NewGameLocation)address).floor != (Object)null && ((NewGameLocation)address).floor.buildingEntrances != null && ((NewGameLocation)address).floor.buildingEntrances.Count > 0)
		{
			Plugin.LogDebug($"[SpawnItemBuildingEntrance] Checking {((NewGameLocation)address).floor.buildingEntrances.Count} entrances from floor");
			Enumerator<NewWall> enumerator2 = ((NewGameLocation)address).floor.buildingEntrances.GetEnumerator();
			while (enumerator2.MoveNext())
			{
				NewWall current2 = enumerator2.Current;
				if (current2 != null)
				{
					NewNode node2 = current2.otherWall.node;
					if (node2 != null && (Object)(object)node2.gameLocation != (Object)null && (Object)(object)node2.gameLocation.thisAsStreet != (Object)null)
					{
						val3 = current2;
						Plugin.LogDebug("[SpawnItemBuildingEntrance] Found street entrance in building entrances");
						break;
					}
				}
			}
		}
		if (val3 == null)
		{
			List<NodeAccess> entrances = ((NewGameLocation)address).entrances;
			if (entrances == null || entrances.Count == 0)
			{
				ManualLogSource log3 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(51, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] No entrances found for ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)address).name);
				}
				log3.LogWarning(val);
				return null;
			}
			Enumerator<NodeAccess> enumerator3 = entrances.GetEnumerator();
			while (enumerator3.MoveNext())
			{
				NodeAccess current3 = enumerator3.Current;
				if (current3.wall != null)
				{
					NewNode node3 = current3.wall.otherWall.node;
					if (node3 != null && (Object)(object)node3.gameLocation != (Object)null && (Object)(object)node3.gameLocation.thisAsStreet != (Object)null)
					{
						val3 = current3.wall;
						Plugin.LogDebug("[SpawnItemBuildingEntrance] Found street entrance from address entrances for " + ((Object)address).name);
						break;
					}
				}
			}
		}
		if (val3 != null)
		{
			val2 = val3;
			Plugin.LogDebug("[SpawnItemBuildingEntrance] Using main entrance to street for building");
		}
		else
		{
			if (((NewGameLocation)address).entrances == null || ((NewGameLocation)address).entrances.Count <= 0)
			{
				ManualLogSource log4 = PluginController<Plugin, IEmptyBindings>.Log;
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(70, 0, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] No entrances found for building or address");
				}
				log4.LogWarning(val);
				return null;
			}
			val2 = ((NewGameLocation)address).entrances[0].wall;
			Plugin.LogDebug("[SpawnItemBuildingEntrance] No street entrance found, using first address entrance for " + ((Object)address).name);
		}
		if (val2 == null)
		{
			ManualLogSource log5 = PluginController<Plugin, IEmptyBindings>.Log;
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(54, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] Entrance wall is null for ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)address).name);
			}
			log5.LogWarning(val);
			return null;
		}
		Plugin.LogDebug("[SpawnItemBuildingEntrance] Using entrance for " + ((Object)address).name);
		NewNode node4 = val2.otherWall.node;
		bool flag2 = false;
		if (node4 != null && (Object)(object)node4.gameLocation != (Object)null)
		{
			if ((Object)(object)node4.gameLocation.thisAsStreet != (Object)null)
			{
				flag2 = true;
				Plugin.LogDebug("[SpawnItemBuildingEntrance] Found street node on otherWall side for " + ((Object)address).name);
			}
			else if ((Object)(object)node4.gameLocation != (Object)(object)address)
			{
				flag2 = true;
				Plugin.LogDebug("[SpawnItemBuildingEntrance] Found outside node on otherWall side for " + ((Object)address).name);
			}
		}
		if (!flag2)
		{
			node4 = val2.node;
			if (node4 != null && (Object)(object)node4.gameLocation != (Object)null)
			{
				if ((Object)(object)node4.gameLocation.thisAsStreet != (Object)null)
				{
					flag2 = true;
					Plugin.LogDebug("[SpawnItemBuildingEntrance] Found street node on wall side for " + ((Object)address).name);
				}
				else if ((Object)(object)node4.gameLocation != (Object)(object)address)
				{
					flag2 = true;
					Plugin.LogDebug("[SpawnItemBuildingEntrance] Found outside node on wall side for " + ((Object)address).name);
				}
			}
		}
		if (!flag2)
		{
			ManualLogSource log6 = PluginController<Plugin, IEmptyBindings>.Log;
			BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(83, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[SpawnItemBuildingEntrance] Could not find a valid street node for the entrance of ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)address).name);
			}
			log6.LogWarning(val);
			return null;
		}
		Plugin.LogDebug($"[SpawnItemBuildingEntrance] Found entrance node at {node4.nodeCoord} for {((Object)address).name}");
		Vector3 position = node4.position;
		Vector3 val4 = val2.otherWall.position - val2.position;
		Vector3 val5 = ((Vector3)(ref val4)).normalized;
		if (val5 == Vector3.zero)
		{
			val5 = Vector3.forward;
		}
		switch (subLocationTypeBuildingEntrances)
		{
		case SubLocationTypeBuildingEntrances.Inside:
		{
			float num2 = -2f;
			spawnPosition = position + val5 * num2;
			spawnPosition.y += 0f;
			spawnPosition.z += Random.Range(-0.5f, 0.5f);
			spawnPosition.x += Random.Range(-0.5f, 0.5f);
			break;
		}
		case SubLocationTypeBuildingEntrances.Outside:
		{
			float num = 1f;
			spawnPosition = position + val5 * num;
			spawnPosition.y += 0.05f;
			spawnPosition.z += Random.Range(-0.5f, 0.5f);
			spawnPosition.x += Random.Range(-0.5f, 0.3f);
			break;
		}
		}
		Plugin.LogDebug($"[SpawnItemBuildingEntrance] Entrance position: {position}, Wall direction: {val5}");
		Plugin.LogDebug($"[SpawnItemBuildingEntrance] Calculated spawn position: {spawnPosition}");
		List<Passed> val6 = new List<Passed>();
		val6.Add(new Passed((PassedVarType)3, (float)node4.room.roomID, (string)null));
		try
		{
			float num3 = Random.Range(0f, 360f);
			Vector3 val7 = default(Vector3);
			((Vector3)(ref val7))..ctor(0f, num3, 0f);
			Plugin.LogDebug($"[SpawnItemBuildingEntrance] Using random rotation: {val7}");
			Interactable val8 = InteractableCreator.Instance.CreateWorldInteractable(itemPreset, owner, owner, recipient, spawnPosition, val7, val6, (Object)null, "");
			if (val8 != null)
			{
				val8.node = node4;
				val8.UpdateWorldPositionAndNode(true, true);
				Plugin.LogDebug("[SpawnItemBuildingEntrance] Successfully created item at building entrance");
				Plugin.LogDebug($"[SpawnItemBuildingEntrance] Item position: {val8.wPos}, node: {((val8.node != null