Decompiled source of DetectiveRoutine v1.0.0

DetectiveRoutine.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using DetectiveRoutine.Cruncher;
using DetectiveRoutine.Dialog;
using DetectiveRoutine.Effects;
using DetectiveRoutine.Model;
using DetectiveRoutine.Survey;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.Helpers;
using SOD.Common.Helpers.DialogObjects;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("DetectiveRoutine")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DetectiveRoutine")]
[assembly: AssemblyTitle("DetectiveRoutine")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace DetectiveRoutine
{
	[BepInPlugin("ekem.detectiveroutine", "Detective Routine", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BasePlugin
	{
		private Harmony? _harmony;

		public static ManualLogSource Log { get; private set; }

		public static Settings Cfg { get; private set; }

		public override void Load()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			Log = ((BasePlugin)this).Log;
			Cfg = new Settings(((BasePlugin)this).Config);
			DialogRegistry.Install();
			_harmony = new Harmony("ekem.detectiveroutine");
			_harmony.PatchAll();
			Warrants.Install();
			InstallHeartbeat();
			ManualLogSource log = Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(9, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Detective Routine");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded.");
			}
			log.LogInfo(val);
		}

		private static void InstallHeartbeat()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			ClassInjector.RegisterTypeInIl2Cpp<Heartbeat>();
			ClassInjector.RegisterTypeInIl2Cpp<WarrantsApp>();
			ClassInjector.RegisterTypeInIl2Cpp<ReportsApp>();
			GameObject val = new GameObject("Detective RoutineHeartbeat");
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
			val.AddComponent<Heartbeat>();
		}
	}
	public class Settings
	{
		public readonly ConfigEntry<bool> OnTheForce;

		public readonly ConfigEntry<bool> HireInGame;

		public readonly ConfigEntry<float> ApplicationHours;

		public readonly ConfigEntry<float> ShiftStart;

		public readonly ConfigEntry<float> ShiftEnd;

		public readonly ConfigEntry<string> ShiftDays;

		public readonly ConfigEntry<float> LateWindowHours;

		public readonly ConfigEntry<float> WorkDaysPerYear;

		public readonly ConfigEntry<float> FallbackShiftPay;

		public readonly ConfigEntry<float> BonusShifts;

		public readonly ConfigEntry<int> BonusMinShifts;

		public readonly ConfigEntry<float> DockShifts;

		public readonly ConfigEntry<float> ProbationDays;

		public readonly ConfigEntry<float> ProbationChancePenalty;

		public readonly ConfigEntry<float> PaperworkHours;

		public readonly ConfigEntry<float> CoolDays;

		public readonly ConfigEntry<float> BadgeHours;

		public readonly ConfigEntry<bool> CaptainWorkweek;

		public readonly ConfigEntry<float> ReportDays;

		public readonly ConfigEntry<float> ShiftReportHours;

		public readonly ConfigEntry<float> ExplanationHours;

		public readonly ConfigEntry<float> SceneReportHours;

		public readonly ConfigEntry<float> CaseReportHours;

		public readonly ConfigEntry<float> FocusedWriteBonus;

		public readonly ConfigEntry<float> SceneMinutesPerLink;

		public readonly ConfigEntry<float> SceneReportMaxHours;

		public readonly ConfigEntry<float> WarrantAppHours;

		public readonly ConfigEntry<float> WarrantMinutesPerGround;

		public readonly ConfigEntry<float> WarrantAppMaxHours;

		public readonly ConfigEntry<float> HoursToTimeOfDeath;

		public readonly ConfigEntry<float> HoursToWeapon;

		public readonly ConfigEntry<float> SceneAccessHours;

		public readonly ConfigEntry<float> ReviewHours;

		public readonly ConfigEntry<float> NoGroundsChance;

		public readonly ConfigEntry<int> WarrantsPerDay;

		public readonly ConfigEntry<float> WarrantHours;

		public readonly ConfigEntry<bool> CarryablePrintouts;

		public readonly ConfigEntry<bool> DebugLogging;

		public readonly ConfigEntry<bool> DebugKeys;

		public readonly ConfigEntry<KeyCode> BoardKey;

		public readonly ConfigEntry<KeyCode> WarrantKey;

		public readonly ConfigEntry<KeyCode> GrantKey;

		public readonly ConfigEntry<KeyCode> BuildingKey;

		public readonly ConfigEntry<KeyCode> ReportKey;

		public Settings(ConfigFile config)
		{
			OnTheForce = config.Bind<bool>("Employment", "OnTheForce", true, "Enable the detective career: joining an Enforcer Division, crime scene briefings, access, search warrants. Off means the plain game.");
			HireInGame = config.Bind<bool>("Employment", "HireInGame", true, "Apply for the job at the City Hall front desk. Off: you join the division whose cruncher you first log into with your own account, no application needed.");
			ApplicationHours = config.Bind<float>("Employment", "ApplicationHours", 4f, "Game hours until your application is answered.");
			ShiftStart = config.Bind<float>("Shifts", "ShiftStart", 9f, "Hour your shift starts (0-24, 9.5 is 9:30).");
			ShiftEnd = config.Bind<float>("Shifts", "ShiftEnd", 17f, "Hour your shift ends. Earlier than the start means it runs past midnight.");
			ShiftDays = config.Bind<string>("Shifts", "ShiftDays", "monday,tuesday,wednesday,thursday,friday", "Days you work, comma separated.");
			LateWindowHours = config.Bind<float>("Shifts", "LateWindowHours", 1f, "How late you can sign in at your division's cruncher before it counts as being late.");
			WorkDaysPerYear = config.Bind<float>("Pay", "WorkDaysPerYear", 260f, "Your yearly salary divided by this is your pay for one shift.");
			FallbackShiftPay = config.Bind<float>("Pay", "FallbackShiftPay", 150f, "Pay per shift if your position has no salary.");
			BonusShifts = config.Bind<float>("Pay", "BonusShifts", 2f, "Weekly bonus for a clean week (no late arrivals, missed shifts or overdue reports), in shifts' pay.");
			BonusMinShifts = config.Bind<int>("Pay", "BonusMinShifts", 4, "Shifts you must have worked in the week to earn the bonus.");
			DockShifts = config.Bind<float>("Discipline", "DockShifts", 2f, "Second strike: this many shifts' pay comes out of your next pay.");
			ProbationDays = config.Bind<float>("Discipline", "ProbationDays", 7f, "Third strike: probation for this many game days. Warrant reviews take twice as long and are granted less often; enforcers tell you less and let you in for less time.");
			ProbationChancePenalty = config.Bind<float>("Discipline", "ProbationChancePenalty", 0.2f, "How much less likely a warrant is granted while you are on probation.");
			PaperworkHours = config.Bind<float>("Discipline", "PaperworkHours", 4f, "Third strike also hands you disciplinary paperwork: a report this many game hours long.");
			CaptainWorkweek = config.Bind<bool>("Pay", "CaptainWorkweek", true, "Your captain works Monday to Friday (some captains only work three days a week, which would leave your warrants and pay waiting).");
			BadgeHours = config.Bind<float>("Badge", "BadgeHours", 1f, "After you show your badge, questions to that person can't be refused for this many game hours. Using it to get into their home without a warrant is a strike.");
			CoolDays = config.Bind<float>("Discipline", "CoolDays", 7f, "Every this many game days without a new strike, one strike is forgiven. Four strikes and you're dismissed.");
			ReportDays = config.Bind<float>("Reports", "ReportDays", 3f, "Game days you have to write a report before it is overdue.");
			ShiftReportHours = config.Bind<float>("Reports", "ShiftReportHours", 1f, "Game hours it takes to write a shift report. Time runs fast while you write.");
			ExplanationHours = config.Bind<float>("Reports", "ExplanationHours", 0.5f, "Game hours it takes to explain a late arrival or a missed shift.");
			SceneReportHours = config.Bind<float>("Reports", "SceneReportHours", 1.5f, "Game hours it takes to write up a crime scene.");
			CaseReportHours = config.Bind<float>("Reports", "CaseReportHours", 3f, "Game hours it takes to write the report after you hand a case in.");
			FocusedWriteBonus = config.Bind<float>("Reports", "FocusedWriteBonus", 1.5f, "How much faster you write while Focused (coffee and the like). 1 turns it off.");
			SceneMinutesPerLink = config.Bind<float>("Reports", "SceneMinutesPerLink", 10f, "Extra game minutes to write up a crime scene for every piece of evidence on your board linked to the scene or the victim.");
			SceneReportMaxHours = config.Bind<float>("Reports", "SceneReportMaxHours", 4f, "A crime scene write-up never takes longer than this, in game hours.");
			WarrantAppHours = config.Bind<float>("Reports", "WarrantAppHours", 0.25f, "Game hours to write a search warrant application with no grounds.");
			WarrantMinutesPerGround = config.Bind<float>("Reports", "WarrantMinutesPerGround", 10f, "Extra game minutes to write a warrant application for every ground you list.");
			WarrantAppMaxHours = config.Bind<float>("Reports", "WarrantAppMaxHours", 2f, "A warrant application never takes longer than this, in game hours.");
			HoursToTimeOfDeath = config.Bind<float>("Briefing", "HoursToTimeOfDeath", 1f, "Game hours after the enforcers arrive before they can tell you the time of death.");
			HoursToWeapon = config.Bind<float>("Briefing", "HoursToWeapon", 2f, "Game hours after the enforcers arrive before they can tell you what the victim was killed with.");
			SceneAccessHours = config.Bind<float>("Access", "SceneAccessHours", 2f, "How long the pass lasts when an enforcer lets you into a crime scene, in game hours.");
			ReviewHours = config.Bind<float>("Warrants", "ReviewHours", 6f, "Game hours to review a search warrant request with no grounds. Every piece of evidence linked to the place on your case board makes it faster.");
			NoGroundsChance = config.Bind<float>("Warrants", "NoGroundsChance", 0.3f, "Chance a request with no grounds is granted. With grounds it starts at 0.7 and grows.");
			WarrantsPerDay = config.Bind<int>("Warrants", "WarrantsPerDay", 3, "How many search warrant requests you can file in 24 game hours.");
			WarrantHours = config.Bind<float>("Warrants", "WarrantHours", 24f, "How long a granted search warrant lasts, in game hours.");
			CarryablePrintouts = config.Bind<bool>("Printouts", "CarryablePrintouts", true, "Printed vmails and database records can be picked up and carried, not just pinned. Print your warrant to leave a copy at the door.");
			DebugLogging = config.Bind<bool>("Debug", "DebugLogging", false, "Write what the mod does to LogOutput.log.");
			DebugKeys = config.Bind<bool>("Debug", "DebugKeys", false, "Enable the debug keys below.");
			BoardKey = config.Bind<KeyCode>("Debug", "BoardKey", (KeyCode)286, "Write the places on your case board and the grounds for a warrant on each to the log.");
			WarrantKey = config.Bind<KeyCode>("Debug", "WarrantKey", (KeyCode)287, "File a search warrant request for the place you pinned last. Stand-in until the cruncher app exists.");
			GrantKey = config.Bind<KeyCode>("Debug", "GrantKey", (KeyCode)285, "Grant a search warrant for the place you pinned last right away, letter included. For testing.");
			BuildingKey = config.Bind<KeyCode>("Debug", "BuildingKey", (KeyCode)284, "Write every address in the building you are in to the log, with its company and staff.");
			ReportKey = config.Bind<KeyCode>("Debug", "ReportKey", (KeyCode)283, "Add a test report to your queue, so you don't have to wait for the end of a shift.");
		}
	}
	public static class PluginInfo
	{
		public const string Guid = "ekem.detectiveroutine";

		public const string Name = "Detective Routine";

		public const string Version = "1.0.0";
	}
}
namespace DetectiveRoutine.Survey
{
	public static class BuildingSurvey
	{
		public static void Run()
		{
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e4: Expected O, but got Unknown
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_0344: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				Player instance = Player.Instance;
				NewBuilding val = ((instance != null) ? ((Actor)instance).currentBuilding : null);
				CityData instance2 = CityData.Instance;
				Dictionary<int, NewAddress> val2 = ((instance2 != null) ? instance2.addressDictionary : null);
				if ((Object)(object)val == (Object)null || val2 == null)
				{
					Plugin.Log.LogInfo((object)"[building] you are not inside a building");
					return;
				}
				ManualLogSource log = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(14, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[building] ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)val).name);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" (");
					BepInExInfoLogInterpolatedStringHandler obj = val3;
					BuildingPreset preset = val.preset;
					((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((preset != null) ? ((Object)preset).name : null);
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(")");
				}
				log.LogInfo(val3);
				Enumerator<int, NewAddress> enumerator = val2.GetEnumerator();
				while (enumerator.MoveNext())
				{
					NewAddress value = enumerator.Current.Value;
					if ((Object)(object)((value != null) ? ((NewGameLocation)value).building : null) == (Object)null || ((Il2CppObjectBase)((NewGameLocation)value).building).Pointer != ((Il2CppObjectBase)val).Pointer)
					{
						continue;
					}
					Company company = value.company;
					ManualLogSource log2 = Plugin.Log;
					DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(23, 3);
					defaultInterpolatedStringHandler.AppendLiteral("[building]   ");
					defaultInterpolatedStringHandler.AppendFormatted(((Object)value).name);
					defaultInterpolatedStringHandler.AppendLiteral(" [");
					AddressPreset addressPreset = value.addressPreset;
					defaultInterpolatedStringHandler.AppendFormatted((addressPreset != null) ? ((Object)addressPreset).name : null);
					defaultInterpolatedStringHandler.AppendLiteral("] floor ");
					NewFloor floor = ((NewGameLocation)value).floor;
					defaultInterpolatedStringHandler.AppendFormatted((floor != null) ? new int?(floor.floor) : ((int?)null));
					string text = defaultInterpolatedStringHandler.ToStringAndClear();
					object obj2;
					if (company != null)
					{
						string name = company.name;
						Human director = company.director;
						obj2 = ", company " + name + ", director " + (((director != null) ? director.GetCitizenName() : null) ?? "-");
					}
					else
					{
						obj2 = "";
					}
					IntPtr pointer = ((Il2CppObjectBase)value).Pointer;
					NewGameLocation currentGameLocation = ((Actor)instance).currentGameLocation;
					IntPtr? obj3;
					if (currentGameLocation == null)
					{
						obj3 = null;
					}
					else
					{
						NewAddress thisAsAddress = currentGameLocation.thisAsAddress;
						obj3 = ((thisAsAddress != null) ? new IntPtr?(((Il2CppObjectBase)thisAsAddress).Pointer) : ((IntPtr?)null));
					}
					log2.LogInfo((object)(text + (string?)obj2 + ((pointer == obj3) ? "  <- you are here" : "")));
					List<Occupation> val4 = ((company != null) ? company.companyRoster : null);
					if (val4 == null)
					{
						continue;
					}
					HashSet<IntPtr> hashSet = new HashSet<IntPtr>();
					Enumerator<Occupation> enumerator2;
					if (company.currentStaff != null)
					{
						enumerator2 = company.currentStaff.GetEnumerator();
						while (enumerator2.MoveNext())
						{
							Occupation current = enumerator2.Current;
							if (current != null)
							{
								hashSet.Add(((Il2CppObjectBase)current).Pointer);
							}
						}
					}
					enumerator2 = val4.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						Occupation current2 = enumerator2.Current;
						Human val5 = ((current2 != null) ? current2.employee : null);
						if (current2 == null)
						{
							continue;
						}
						IntPtr? obj4;
						if (val5 == null)
						{
							obj4 = null;
						}
						else
						{
							NewGameLocation currentGameLocation2 = ((Actor)val5).currentGameLocation;
							if (currentGameLocation2 == null)
							{
								obj4 = null;
							}
							else
							{
								NewAddress thisAsAddress2 = currentGameLocation2.thisAsAddress;
								obj4 = ((thisAsAddress2 != null) ? new IntPtr?(((Il2CppObjectBase)thisAsAddress2).Pointer) : ((IntPtr?)null));
							}
						}
						bool flag2 = obj4 == ((Il2CppObjectBase)value).Pointer;
						ManualLogSource log3 = Plugin.Log;
						val3 = new BepInExInfoLogInterpolatedStringHandler(22, 11, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[building]     ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(current2.name);
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(current2.startTimeDecimalHour, "0.#");
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("-");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(current2.endTimeDecialHour, "0.#");
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" (");
							BepInExInfoLogInterpolatedStringHandler obj5 = val3;
							OccupationPreset preset2 = current2.preset;
							((BepInExLogInterpolatedStringHandler)obj5).AppendFormatted<string>((preset2 != null) ? ((Object)preset2).name : null);
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((SoCustomComparison)(object)current2.preset != (SoCustomComparison)null && current2.preset.receptionist) ? ", receptionist" : "");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(current2.isOwner ? ", owner" : "");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(current2.teamLeader ? ", team leader" : "");
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("): ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((val5 != null) ? val5.GetCitizenName() : null) ?? "vacant");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(hashSet.Contains(((Il2CppObjectBase)current2).Pointer) ? ", on shift" : "");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(flag2 ? ", here now" : "");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)(object)val5 != (Object)null && ((Actor)val5).isEnforcer) ? ", enforcer" : "");
						}
						log3.LogInfo(val3);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val6 = new BepInExErrorLogInterpolatedStringHandler(26, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[building] survey failed: ");
					((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<Exception>(ex);
				}
				log4.LogError(val6);
			}
		}
	}
	[HarmonyPatch(typeof(MainMenuController), "Start")]
	public static class CruncherSurvey
	{
		private static bool _done;

		private static readonly string[] DumpApps = new string[0];

		[HarmonyPostfix]
		public static void Postfix()
		{
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a0: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			if (_done || !Plugin.Cfg.DebugLogging.Value)
			{
				return;
			}
			_done = true;
			bool flag = default(bool);
			try
			{
				Il2CppArrayBase<CruncherAppPreset> val = Resources.FindObjectsOfTypeAll<CruncherAppPreset>();
				ManualLogSource log = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[cruncher] ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val.Length);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" app presets");
				}
				log.LogInfo(val2);
				foreach (CruncherAppPreset app in val)
				{
					List<GameObject> content = app.appContent;
					string text = ((content == null) ? "-" : string.Join(", ", from i in Enumerable.Range(0, content.Count)
						select (!((Object)(object)content[i] == (Object)null)) ? (((Object)content[i]).name + "<" + Components(content[i]) + ">") : "null"));
					string text2 = ((app.onlyInAddresses == null) ? "" : string.Join(",", Enumerable.Range(0, app.onlyInAddresses.Count).Select(delegate(int i)
					{
						AddressPreset obj2 = app.onlyInAddresses[i];
						return ((obj2 != null) ? ((Object)obj2).name : null) ?? "?";
					})));
					ManualLogSource log2 = Plugin.Log;
					val2 = new BepInExInfoLogInterpolatedStringHandler(110, 8, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[cruncher]   ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)app).name);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": alwaysInstalled ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(app.alwaysInstalled);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", companyOnly ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(app.companyOnly);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", ");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("onlyIfOwner ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(app.onlyIfOwner);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", residential ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(app.onlyIfResidential);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", ");
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("conditions ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(app.installationConditions?.Count ?? 0);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", addresses [");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text2);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("], content ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
					}
					log2.LogInfo(val2);
				}
				foreach (InteractablePreset item in Resources.FindObjectsOfTypeAll<InteractablePreset>())
				{
					List<CruncherAppPreset> extra = item.additionalApps;
					if (extra != null && extra.Count != 0)
					{
						Plugin.Log.LogInfo((object)("[cruncher] computer " + ((Object)item).name + ": " + string.Join(", ", Enumerable.Range(0, extra.Count).Select(delegate(int i)
						{
							CruncherAppPreset obj2 = extra[i];
							return ((obj2 != null) ? ((Object)obj2).name : null) ?? "null";
						}))));
					}
				}
				string[] dumpApps = DumpApps;
				foreach (string name in dumpApps)
				{
					CruncherAppPreset val3 = ((IEnumerable<CruncherAppPreset>)val).FirstOrDefault((Func<CruncherAppPreset, bool>)((CruncherAppPreset a) => ((Object)a).name == name));
					if (((val3 != null) ? val3.appContent : null) != null)
					{
						for (int num2 = 0; num2 < val3.appContent.Count; num2++)
						{
							GameObject obj = val3.appContent[num2];
							Dump((obj != null) ? obj.transform : null, 0);
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(26, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[cruncher] survey failed: ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Exception>(ex);
				}
				log3.LogError(val4);
			}
		}

		private static string Components(GameObject go)
		{
			return string.Join("+", ((IEnumerable<Component>)go.GetComponents<Component>()).Select((Component c) => (!((Object)(object)c == (Object)null)) ? ((MemberInfo)((Object)c).GetIl2CppType()).Name : "null"));
		}

		private static void Dump(Transform? t, int depth)
		{
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)t == (Object)null) && depth <= 8)
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append(' ', depth * 2).Append(((Object)t).name).Append(" <")
					.Append(Components(((Component)t).gameObject))
					.Append('>');
				TextMeshProUGUI component = ((Component)t).GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component != (Object)null)
				{
					stringBuilder.Append(" \"").Append(((TMP_Text)component).text?.Replace("\n", " ")).Append('"');
				}
				if (!((Component)t).gameObject.activeSelf)
				{
					stringBuilder.Append(" (inactive)");
				}
				RectTransform val = ((Il2CppObjectBase)t).TryCast<RectTransform>();
				if ((Object)(object)val != (Object)null)
				{
					StringBuilder stringBuilder2 = stringBuilder;
					StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(12, 4, stringBuilder2);
					handler.AppendLiteral(" rect ");
					Rect rect = val.rect;
					handler.AppendFormatted(((Rect)(ref rect)).width, "F3");
					handler.AppendLiteral("x");
					rect = val.rect;
					handler.AppendFormatted(((Rect)(ref rect)).height, "F3");
					handler.AppendLiteral(" at ");
					handler.AppendFormatted(val.anchoredPosition.x, "F3");
					handler.AppendLiteral(",");
					handler.AppendFormatted(val.anchoredPosition.y, "F3");
					stringBuilder2.Append(ref handler);
				}
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[cruncher] tree ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<StringBuilder>(stringBuilder);
				}
				log.LogInfo(val2);
				for (int i = 0; i < t.childCount; i++)
				{
					Dump(t.GetChild(i), depth + 1);
				}
			}
		}
	}
	public static class FurnitureSurvey
	{
		public static void Run()
		{
			//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bc: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0336: Expected O, but got Unknown
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Expected O, but got Unknown
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				Player instance = Player.Instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					NewGameLocation currentGameLocation = ((Actor)instance).currentGameLocation;
					obj = ((currentGameLocation != null) ? currentGameLocation.thisAsAddress : null);
				}
				NewAddress val = (NewAddress)obj;
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogInfo((object)"[furniture] not at an address");
					return;
				}
				ManualLogSource log = Plugin.Log;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(15, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture] ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)val).name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" [");
					BepInExInfoLogInterpolatedStringHandler obj2 = val2;
					AddressPreset addressPreset = val.addressPreset;
					((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((addressPreset != null) ? ((Object)addressPreset).name : null);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]");
				}
				log.LogInfo(val2);
				Dictionary<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> furnitureBelongsTo = ((NewGameLocation)val).furnitureBelongsTo;
				if (furnitureBelongsTo != null)
				{
					Enumerator<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> enumerator = furnitureBelongsTo.GetEnumerator();
					while (enumerator.MoveNext())
					{
						KeyValuePair<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> current = enumerator.Current;
						Enumerator<FurnitureLocation, List<Human>> enumerator2 = current.Value.GetEnumerator();
						while (enumerator2.MoveNext())
						{
							KeyValuePair<FurnitureLocation, List<Human>> current2 = enumerator2.Current;
							List<string> list = new List<string>();
							if (current2.Value != null)
							{
								Enumerator<Human> enumerator3 = current2.Value.GetEnumerator();
								while (enumerator3.MoveNext())
								{
									Human current3 = enumerator3.Current;
									list.Add(((current3 != null) ? current3.GetCitizenName() : null) ?? "?");
								}
							}
							ManualLogSource log2 = Plugin.Log;
							val2 = new BepInExInfoLogInterpolatedStringHandler(26, 3, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture]   owned ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<OwnershipClass>(current.Key);
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Describe(current2.Key));
								((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> ");
								((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>((list.Count == 0) ? "nobody" : string.Join(", ", list));
							}
							log2.LogInfo(val2);
						}
					}
				}
				if (((NewGameLocation)val).rooms != null)
				{
					Enumerator<NewRoom> enumerator4 = ((NewGameLocation)val).rooms.GetEnumerator();
					while (enumerator4.MoveNext())
					{
						NewRoom current4 = enumerator4.Current;
						if (((current4 != null) ? current4.individualFurniture : null) == null)
						{
							continue;
						}
						ManualLogSource log3 = Plugin.Log;
						val2 = new BepInExInfoLogInterpolatedStringHandler(29, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture]   room ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(current4.name);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(current4.individualFurniture.Count);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" pieces)");
						}
						log3.LogInfo(val2);
						Enumerator<FurnitureLocation> enumerator5 = current4.individualFurniture.GetEnumerator();
						while (enumerator5.MoveNext())
						{
							FurnitureLocation current5 = enumerator5.Current;
							if (!((SoCustomComparison)(object)((current5 != null) ? current5.furniture : null) == (SoCustomComparison)null))
							{
								List<string> list2 = new List<string>();
								Collect(current5.integratedInteractables, list2);
								Collect(current5.spawnedInteractables, list2);
								ManualLogSource log4 = Plugin.Log;
								val2 = new BepInExInfoLogInterpolatedStringHandler(16, 2, ref flag);
								if (flag)
								{
									((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture]     ");
									((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Describe(current5));
									((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>((list2.Count == 0) ? "" : (": " + string.Join(", ", list2)));
								}
								log4.LogInfo(val2);
							}
						}
					}
				}
				if (val.company != null)
				{
					ManualLogSource log5 = Plugin.Log;
					val2 = new BepInExInfoLogInterpolatedStringHandler(38, 2, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture]   work positions: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Desks.All(val).Count);
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", free: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Desks.Free(val).Count);
					}
					log5.LogInfo(val2);
				}
				Company company = val.company;
				List<Occupation> val3 = ((company != null) ? company.companyRoster : null);
				if (val3 == null)
				{
					return;
				}
				Enumerator<Occupation> enumerator6 = val3.GetEnumerator();
				while (enumerator6.MoveNext())
				{
					Occupation current6 = enumerator6.Current;
					Human val4 = ((current6 != null) ? current6.employee : null);
					if (!((Object)(object)val4 == (Object)null))
					{
						Interactable workPosition = val4.workPosition;
						ManualLogSource log6 = Plugin.Log;
						string obj3 = $"[furniture]   {val4.GetCitizenName()} ({current6.name}) works at ";
						object obj4;
						if (workPosition != null)
						{
							DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 3);
							InteractablePreset preset = workPosition.preset;
							defaultInterpolatedStringHandler.AppendFormatted((preset != null) ? ((SoCustomComparison)preset).presetName : null);
							defaultInterpolatedStringHandler.AppendLiteral(" #");
							defaultInterpolatedStringHandler.AppendFormatted(workPosition.id);
							defaultInterpolatedStringHandler.AppendLiteral(" on ");
							defaultInterpolatedStringHandler.AppendFormatted(Describe(workPosition.furnitureParent));
							obj4 = defaultInterpolatedStringHandler.ToStringAndClear();
						}
						else
						{
							obj4 = "nothing";
						}
						log6.LogInfo((object)(obj3 + (string?)obj4));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log7 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[furniture] survey failed: ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<Exception>(ex);
				}
				log7.LogError(val5);
			}
		}

		private static string Describe(FurnitureLocation? f)
		{
			if ((SoCustomComparison)(object)((f != null) ? f.furniture : null) == (SoCustomComparison)null)
			{
				return "none";
			}
			return $"{((Object)f.furniture).name} #{f.id}{(f.furniture.isWorkPosition ? " (work position)" : "")}";
		}

		private static void Collect(List<Interactable>? list, List<string> into)
		{
			if (list == null)
			{
				return;
			}
			Enumerator<Interactable> enumerator = list.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Interactable current = enumerator.Current;
				if (!((SoCustomComparison)(object)((current != null) ? current.preset : null) == (SoCustomComparison)null))
				{
					into.Add($"{((SoCustomComparison)current.preset).presetName} #{current.id}" + (((Object)(object)current.belongsTo != (Object)null) ? (" [" + current.belongsTo.GetCitizenName() + "]") : ""));
				}
			}
		}
	}
}
namespace DetectiveRoutine.Model
{
	public static class Captain
	{
		private static IntPtr _adjusted;

		public static Occupation? Job()
		{
			Company? division = Employment.Division;
			List<Occupation> val = ((division != null) ? division.companyRoster : null);
			if (val == null)
			{
				return null;
			}
			Enumerator<Occupation> enumerator = val.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Occupation current = enumerator.Current;
				if (current != null && current.isOwner && (Object)(object)current.employee != (Object)null)
				{
					return current;
				}
			}
			return null;
		}

		public static bool OnDuty(float time)
		{
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			Occupation val = Job();
			if (val == null)
			{
				return true;
			}
			SessionData instance = SessionData.Instance;
			float startTimeDecimalHour = val.startTimeDecimalHour;
			float endTimeDecialHour = val.endTimeDecialHour;
			float num = default(float);
			WeekDay day = default(WeekDay);
			int num2 = default(int);
			Month val2 = default(Month);
			int num3 = default(int);
			instance.ParseTimeData(time, ref num, ref day, ref num2, ref val2, ref num3);
			if (endTimeDecialHour > startTimeDecimalHour)
			{
				if (num >= startTimeDecimalHour && num < endTimeDecialHour)
				{
					return Works(val, day);
				}
				return false;
			}
			if (num >= startTimeDecimalHour)
			{
				return Works(val, day);
			}
			if (num < endTimeDecialHour)
			{
				float num4 = default(float);
				WeekDay day2 = default(WeekDay);
				instance.ParseTimeData(time - 24f, ref num4, ref day2, ref num3, ref val2, ref num2);
				return Works(val, day2);
			}
			return false;
		}

		private static bool Works(Occupation job, WeekDay day)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			List<WeekDay> workDaysList = job.workDaysList;
			if (workDaysList == null || workDaysList.Count == 0)
			{
				return true;
			}
			Enumerator<WeekDay> enumerator = workDaysList.GetEnumerator();
			while (enumerator.MoveNext())
			{
				if (enumerator.Current == day)
				{
					return true;
				}
			}
			return false;
		}

		public static void EnsureWorkweek()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			if (!Plugin.Cfg.CaptainWorkweek.Value)
			{
				return;
			}
			Occupation val = Job();
			if (val == null || ((Il2CppObjectBase)val).Pointer == _adjusted)
			{
				return;
			}
			WeekDay[] array = new WeekDay[5];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			WeekDay[] array2 = (WeekDay[])(object)array;
			List<WeekDay> workDaysList = val.workDaysList;
			bool flag = workDaysList != null && workDaysList.Count == array2.Length;
			if (flag)
			{
				WeekDay[] array3 = array2;
				foreach (WeekDay val2 in array3)
				{
					if (!workDaysList.Contains(val2))
					{
						flag = false;
					}
				}
			}
			if (!flag)
			{
				List<WeekDay> val3 = new List<WeekDay>();
				WeekDay[] array3 = array2;
				foreach (WeekDay val4 in array3)
				{
					val3.Add(val4);
				}
				val.workDaysList = val3;
				ManualLogSource log = Plugin.Log;
				bool flag2 = default(bool);
				BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[pay] ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(Name());
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" now works Monday to Friday");
				}
				log.LogInfo(val5);
			}
			_adjusted = ((Il2CppObjectBase)val).Pointer;
		}

		public static void Memo(string subject, string text)
		{
			Company division = Employment.Division;
			Human val = ((division != null) ? division.director : null);
			Human val2 = val ?? WarrantMail.Sender();
			if (!((Object)(object)val2 == (Object)null))
			{
				WarrantMail.Letter(val2, text, subject.ToUpperInvariant(), (!((Object)(object)val == (Object)null)) ? ("Captain " + val.GetCitizenName() + ", " + division.name) : (((division != null) ? division.name : null) ?? "Enforcer Division"), "memo '" + subject + "'");
			}
		}

		public static float RankAndFileSalary()
		{
			Company? division = Employment.Division;
			List<Occupation> val = ((division != null) ? division.companyRoster : null);
			if (val == null)
			{
				return 0f;
			}
			Enumerator<Occupation> enumerator = val.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Occupation current = enumerator.Current;
				if (current != null && !current.isOwner && !current.teamLeader && current.salary > 0f)
				{
					return current.salary;
				}
			}
			return 0f;
		}

		public static string Name()
		{
			Occupation? obj = Job();
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				Human employee = obj.employee;
				obj2 = ((employee != null) ? employee.GetCitizenName() : null);
			}
			if (obj2 == null)
			{
				obj2 = "the captain";
			}
			return (string)obj2;
		}
	}
	public static class CaseBoard
	{
		public sealed record Place(Evidence Evidence, NewAddress Address);

		public sealed record Ground(string Name, bool Custom, string? Label, string Id = "");

		private const string DefaultLinkName = "Created Link";

		public static HashSet<string> PinnedIds()
		{
			HashSet<string> hashSet = new HashSet<string>();
			CasePanelController instance = CasePanelController.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				Case activeCase = instance.activeCase;
				obj = ((activeCase != null) ? activeCase.caseElements : null);
			}
			List<CaseElement> val = (List<CaseElement>)obj;
			if (val == null)
			{
				return hashSet;
			}
			Enumerator<CaseElement> enumerator = val.GetEnumerator();
			while (enumerator.MoveNext())
			{
				CaseElement current = enumerator.Current;
				if (!string.IsNullOrEmpty((current != null) ? current.id : null))
				{
					hashSet.Add(current.id);
				}
			}
			return hashSet;
		}

		public static List<Place> Places()
		{
			List<Place> list = new List<Place>();
			CasePanelController instance = CasePanelController.Instance;
			object obj;
			if (instance == null)
			{
				obj = null;
			}
			else
			{
				Case activeCase = instance.activeCase;
				obj = ((activeCase != null) ? activeCase.caseElements : null);
			}
			List<CaseElement> val = (List<CaseElement>)obj;
			if (val == null)
			{
				return list;
			}
			Enumerator<CaseElement> enumerator = val.GetEnumerator();
			Evidence val2 = default(Evidence);
			while (enumerator.MoveNext())
			{
				CaseElement current = enumerator.Current;
				if (current == null || string.IsNullOrEmpty(current.id) || !Toolbox.Instance.TryGetEvidence(current.id, ref val2) || val2 == null)
				{
					continue;
				}
				EvidenceLocation obj2 = ((Il2CppObjectBase)val2).TryCast<EvidenceLocation>();
				NewGameLocation val3 = ((obj2 != null) ? obj2.locationController : null);
				if (!((Object)(object)val3 == (Object)null) && !val3.isOutside)
				{
					NewAddress thisAsAddress = val3.thisAsAddress;
					if (!((Object)(object)thisAsAddress == (Object)null))
					{
						list.Add(new Place(val2, thisAsAddress));
					}
				}
			}
			return list;
		}

		public static List<Ground> GroundsFor(Evidence place, HashSet<string> pinned)
		{
			Dictionary<string, Ground> dictionary = new Dictionary<string, Ground>();
			List<FactLink> allFacts = place.allFacts;
			if (allFacts == null)
			{
				return new List<Ground>();
			}
			Enumerator<FactLink> enumerator = allFacts.GetEnumerator();
			while (enumerator.MoveNext())
			{
				FactLink current = enumerator.Current;
				Fact val = ((current != null) ? current.fact : null);
				List<Evidence> val2 = ((current != null) ? current.destinationEvidence : null);
				if (val == null || val2 == null)
				{
					continue;
				}
				Enumerator<Evidence> enumerator2 = val2.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					Evidence current2 = enumerator2.Current;
					if (current2 != null && !(current2.evID == place.evID) && pinned.Contains(current2.evID))
					{
						bool isCustom = val.isCustom;
						string label = ((isCustom && !string.IsNullOrWhiteSpace(val.customName) && val.customName != "Created Link") ? val.customName : null);
						if (!dictionary.TryGetValue(current2.evID, out var value) || (!value.Custom && isCustom))
						{
							dictionary[current2.evID] = new Ground(NameOf(current2), isCustom, label, current2.evID);
						}
					}
				}
			}
			return new List<Ground>(dictionary.Values);
		}

		public static int SceneLinks(NewAddress scene)
		{
			HashSet<string> pinned = PinnedIds();
			HashSet<string> hashSet = new HashSet<string>();
			if (((NewGameLocation)scene).evidenceEntry != null)
			{
				foreach (Ground item in GroundsFor((Evidence)(object)((NewGameLocation)scene).evidenceEntry, pinned))
				{
					hashSet.Add(item.Id);
				}
			}
			Murder? obj = CrimeScenes.MurderAt((NewGameLocation)(object)scene);
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				Human victim = obj.victim;
				obj2 = ((victim != null) ? ((Actor)victim).evidenceEntry : null);
			}
			EvidenceWitness val = (EvidenceWitness)obj2;
			if (val != null)
			{
				foreach (Ground item2 in GroundsFor((Evidence)(object)val, pinned))
				{
					hashSet.Add(item2.Id);
				}
			}
			if (((NewGameLocation)scene).evidenceEntry != null)
			{
				hashSet.Remove(((Evidence)((NewGameLocation)scene).evidenceEntry).evID);
			}
			if (val != null)
			{
				hashSet.Remove(((Evidence)val).evID);
			}
			return hashSet.Count;
		}

		public static string NameOf(Evidence evidence)
		{
			try
			{
				string nameForDataKey = evidence.GetNameForDataKey((DataKey)0);
				if (!string.IsNullOrWhiteSpace(nameForDataKey))
				{
					return nameForDataKey;
				}
			}
			catch
			{
			}
			return evidence.evID;
		}
	}
	public static class CrimeScenes
	{
		public sealed record Scene(NewGameLocation Location, EnforcerCall Call, Murder? Murder);

		public static Scene? GuardedBy(Human enforcer)
		{
			GameplayController instance = GameplayController.Instance;
			Dictionary<NewGameLocation, EnforcerCall> val = ((instance != null) ? instance.enforcerCalls : null);
			if (val == null)
			{
				return null;
			}
			int humanID = enforcer.humanID;
			Enumerator<NewGameLocation, EnforcerCall> enumerator = val.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<NewGameLocation, EnforcerCall> current = enumerator.Current;
				EnforcerCall value = current.Value;
				if (value != null && value.isCrimeScene && (value.guard == humanID || (value.response != null && value.response.Contains(humanID))))
				{
					return new Scene(current.Key, value, MurderAt(current.Key));
				}
			}
			return null;
		}

		public static Murder? MurderAt(NewGameLocation location)
		{
			MurderController instance = MurderController.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			List<Murder>[] array = new List<Murder>[2] { instance.activeMurders, instance.inactiveMurders };
			foreach (List<Murder> val in array)
			{
				if (val == null)
				{
					continue;
				}
				for (int num = val.Count - 1; num >= 0; num--)
				{
					Murder val2 = val[num];
					if ((Object)(object)((val2 != null) ? val2.location : null) != (Object)null && ((Il2CppObjectBase)val2.location).Pointer == ((Il2CppObjectBase)location).Pointer)
					{
						return val2;
					}
				}
			}
			return null;
		}
	}
	public static class Desks
	{
		private const string PlacardPreset = "NamePlacard";

		private static bool _placardFailed;

		private const string PhotoPreset = "EmployeePhoto";

		private const string PhotoBoard = "EmployeePhotoBoard";

		private static bool _photoFailed;

		private static bool _noPhotoSpotReported;

		private static bool _noTemplateReported;

		public static int PlacardDesk { get; set; } = -1;

		public static int PlacardId { get; set; } = -1;

		public static List<FurnitureLocation> All(NewAddress office)
		{
			List<FurnitureLocation> list = new List<FurnitureLocation>();
			foreach (FurnitureLocation item in Furniture(office))
			{
				if (item.furniture.isWorkPosition)
				{
					list.Add(item);
				}
			}
			return list;
		}

		public static List<FurnitureLocation> Free(NewAddress office)
		{
			HashSet<IntPtr> hashSet = new HashSet<IntPtr>();
			Dictionary<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> furnitureBelongsTo = ((NewGameLocation)office).furnitureBelongsTo;
			if (furnitureBelongsTo != null)
			{
				Enumerator<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> enumerator = furnitureBelongsTo.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Enumerator<FurnitureLocation, List<Human>> enumerator2 = enumerator.Current.Value.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						KeyValuePair<FurnitureLocation, List<Human>> current = enumerator2.Current;
						if (current.Key != null && current.Value != null && current.Value.Count > 0)
						{
							hashSet.Add(((Il2CppObjectBase)current.Key).Pointer);
						}
					}
				}
			}
			HashSet<string> hashSet2 = new HashSet<string>();
			Company company = office.company;
			List<Occupation> val = ((company != null) ? company.companyRoster : null);
			if (val != null)
			{
				Enumerator<Occupation> enumerator3 = val.GetEnumerator();
				while (enumerator3.MoveNext())
				{
					Occupation current2 = enumerator3.Current;
					Human val2 = ((current2 != null) ? current2.employee : null);
					object obj;
					if (val2 == null)
					{
						obj = null;
					}
					else
					{
						Interactable workPosition = val2.workPosition;
						obj = ((workPosition != null) ? workPosition.furnitureParent : null);
					}
					FurnitureLocation val3 = (FurnitureLocation)obj;
					if (!((Object)(object)val2 == (Object)null) && val3 != null && !((Actor)val2).isPlayer)
					{
						hashSet.Add(((Il2CppObjectBase)val3).Pointer);
						if ((SoCustomComparison)(object)val3.furniture != (SoCustomComparison)null)
						{
							hashSet2.Add(((Object)val3.furniture).name);
						}
					}
				}
			}
			List<FurnitureLocation> list = new List<FurnitureLocation>();
			foreach (FurnitureLocation item in All(office))
			{
				if (!hashSet.Contains(((Il2CppObjectBase)item).Pointer) && (hashSet2.Count == 0 || hashSet2.Contains(((Object)item.furniture).name)))
				{
					list.Add(item);
				}
			}
			return list;
		}

		public static FurnitureLocation? Find(NewAddress office, int id)
		{
			foreach (FurnitureLocation item in Furniture(office))
			{
				if (item.id == id)
				{
					return item;
				}
			}
			return null;
		}

		public static void Claim(NewAddress office, FurnitureLocation desk)
		{
			Player instance = Player.Instance;
			if (!((Object)(object)instance == (Object)null))
			{
				Own(office, desk, (OwnershipClass)2, (Human)(object)instance, own: true);
				FurnitureLocation val = Drawers(office, desk);
				if (val != null)
				{
					Own(office, val, (OwnershipClass)4, (Human)(object)instance, own: true);
				}
				Interactable val2 = WorkSpot(desk);
				if (val2 != null && (((Human)instance).workPosition == null || ((Il2CppObjectBase)((Human)instance).workPosition).Pointer != ((Il2CppObjectBase)val2).Pointer))
				{
					((Human)instance).SetWorkFurniture(val2);
				}
				EnsurePlacard(office, desk, (Human)(object)instance);
			}
		}

		private static void EnsurePlacard(NewAddress office, FurnitureLocation desk, Human player)
		{
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Expected O, but got Unknown
			List<Interactable> spawnedInteractables = desk.spawnedInteractables;
			bool flag = default(bool);
			if (spawnedInteractables != null)
			{
				List<Interactable> list = new List<Interactable>();
				Enumerator<Interactable> enumerator = spawnedInteractables.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Interactable current = enumerator.Current;
					if ((SoCustomComparison)(object)((current != null) ? current.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)current.preset).presetName == "NamePlacard")
					{
						list.Add(current);
					}
				}
				for (int i = 1; i < list.Count; i++)
				{
					list[i].SafeDelete(false);
				}
				if (list.Count > 1)
				{
					ManualLogSource log = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] removed ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list.Count - 1);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" extra name placards from your desk");
					}
					log.LogInfo(val);
				}
				if (list.Count > 0)
				{
					PlacardDesk = desk.id;
					PlacardId = list[0].id;
					return;
				}
			}
			if (PlacardDesk == desk.id)
			{
				return;
			}
			Interactable val2 = null;
			foreach (FurnitureLocation item in Furniture(office))
			{
				if (((Il2CppObjectBase)item).Pointer == ((Il2CppObjectBase)desk).Pointer || item.spawnedInteractables == null)
				{
					continue;
				}
				Enumerator<Interactable> enumerator = item.spawnedInteractables.GetEnumerator();
				while (enumerator.MoveNext())
				{
					Interactable current3 = enumerator.Current;
					if ((SoCustomComparison)(object)((current3 != null) ? current3.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)current3.preset).presetName == "NamePlacard" && (val2 == null || ((Object)item.furniture).name == ((Object)desk.furniture).name))
					{
						val2 = current3;
					}
				}
			}
			if (val2 == null)
			{
				if (!_noTemplateReported)
				{
					ManualLogSource log2 = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(62, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] no name placard in ");
						BepInExInfoLogInterpolatedStringHandler obj = val;
						Company company = office.company;
						((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((company != null) ? company.name : null);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" to copy, your desk stays without one");
					}
					log2.LogInfo(val);
				}
				_noTemplateReported = true;
			}
			else
			{
				if (_placardFailed)
				{
					return;
				}
				try
				{
					Interactable val3 = InteractableCreator.Instance.CreateFurnitureSpawnedInteractable(val2.preset, desk, val2.subObject, player, player, (Human)null, new List<Passed>(), (LightingPreset)null, (Object)null, "");
					Plugin.Log.LogInfo((object)((val3 == null) ? "[job] the game refused to place your name placard" : $"[job] name placard placed on your desk (#{val3.id})"));
					if (val3 == null)
					{
						_placardFailed = true;
						return;
					}
					PlacardDesk = desk.id;
					PlacardId = val3.id;
				}
				catch (Exception ex)
				{
					_placardFailed = true;
					ManualLogSource log3 = Plugin.Log;
					BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(69, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[job] could not place your name placard, giving up for this session: ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(ex.Message);
					}
					log3.LogError(val4);
				}
			}
		}

		public static void EnsurePhoto(NewAddress office, Human player)
		{
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Expected O, but got Unknown
			if (_photoFailed)
			{
				return;
			}
			bool flag = default(bool);
			foreach (FurnitureLocation item in Furniture(office))
			{
				if (((Object)item.furniture).name != "EmployeePhotoBoard")
				{
					continue;
				}
				Interactable val = null;
				HashSet<IntPtr> hashSet = new HashSet<IntPtr>();
				if (item.spawnedInteractables != null)
				{
					Enumerator<Interactable> enumerator2 = item.spawnedInteractables.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						Interactable current2 = enumerator2.Current;
						if ((SoCustomComparison)(object)((current2 != null) ? current2.preset : null) == (SoCustomComparison)null)
						{
							continue;
						}
						if (current2.subObject != null)
						{
							hashSet.Add(((Il2CppObjectBase)current2.subObject).Pointer);
						}
						if (!(((SoCustomComparison)current2.preset).presetName != "EmployeePhoto"))
						{
							if ((Object)(object)current2.belongsTo != (Object)null && ((Il2CppObjectBase)current2.belongsTo).Pointer == ((Il2CppObjectBase)player).Pointer)
							{
								return;
							}
							if (val == null)
							{
								val = current2;
							}
						}
					}
				}
				if (((val != null) ? val.subObject : null) == null)
				{
					continue;
				}
				SubObject val2 = null;
				List<SubObject> subObjects = item.furniture.subObjects;
				if (subObjects != null)
				{
					Enumerator<SubObject> enumerator3 = subObjects.GetEnumerator();
					while (enumerator3.MoveNext())
					{
						SubObject current3 = enumerator3.Current;
						if (current3 != null && !hashSet.Contains(((Il2CppObjectBase)current3).Pointer) && (SoCustomComparison)(object)current3.preset != (SoCustomComparison)null && (SoCustomComparison)(object)val.subObject.preset != (SoCustomComparison)null && ((Il2CppObjectBase)current3.preset).Pointer == ((Il2CppObjectBase)val.subObject.preset).Pointer)
						{
							val2 = current3;
							break;
						}
					}
				}
				if (val2 == null)
				{
					if (!_noPhotoSpotReported)
					{
						ManualLogSource log = Plugin.Log;
						BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(50, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[job] no free spot on the employee photo board in ");
							Company company = office.company;
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>((company != null) ? company.name : null);
						}
						log.LogInfo(val3);
					}
					_noPhotoSpotReported = true;
					break;
				}
				try
				{
					Interactable val4 = InteractableCreator.Instance.CreateFurnitureSpawnedInteractable(val.preset, item, val2, player, player, (Human)null, new List<Passed>(), (LightingPreset)null, (Object)null, "");
					Plugin.Log.LogInfo((object)((val4 == null) ? "[job] the game refused to pin your photo" : $"[job] your photo pinned to the employee board (#{val4.id})"));
					if (val4 == null)
					{
						_photoFailed = true;
					}
					break;
				}
				catch (Exception ex)
				{
					_photoFailed = true;
					ManualLogSource log2 = Plugin.Log;
					BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(60, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[job] could not pin your photo, giving up for this session: ");
						((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ex.Message);
					}
					log2.LogError(val5);
					break;
				}
			}
		}

		public static void RemovePhoto(NewAddress office, Human player)
		{
			foreach (FurnitureLocation item in Furniture(office))
			{
				if (((Object)item.furniture).name != "EmployeePhotoBoard" || item.spawnedInteractables == null)
				{
					continue;
				}
				for (int num = item.spawnedInteractables.Count - 1; num >= 0; num--)
				{
					Interactable val = item.spawnedInteractables[num];
					if ((SoCustomComparison)(object)((val != null) ? val.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)val.preset).presetName == "EmployeePhoto" && (Object)(object)val.belongsTo != (Object)null && ((Il2CppObjectBase)val.belongsTo).Pointer == ((Il2CppObjectBase)player).Pointer)
					{
						val.SafeDelete(false);
					}
				}
			}
		}

		public static void Release(NewAddress office, FurnitureLocation desk)
		{
			Player instance = Player.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				return;
			}
			Own(office, desk, (OwnershipClass)2, (Human)(object)instance, own: false);
			PlacardDesk = -1;
			CityData instance2 = CityData.Instance;
			Dictionary<int, Interactable> val = ((instance2 != null) ? instance2.savableInteractableDictionary : null);
			Interactable val2 = default(Interactable);
			if (PlacardId >= 0 && val != null && val.TryGetValue(PlacardId, ref val2) && val2 != null)
			{
				val2.SafeDelete(false);
			}
			PlacardId = -1;
			FurnitureLocation val3 = Drawers(office, desk);
			if (val3 != null)
			{
				Own(office, val3, (OwnershipClass)4, (Human)(object)instance, own: false);
			}
			Interactable val4 = WorkSpot(desk);
			if (val4 != null && ((Human)instance).workPosition != null && ((Il2CppObjectBase)((Human)instance).workPosition).Pointer == ((Il2CppObjectBase)val4).Pointer)
			{
				((Human)instance).SetWorkFurniture((Interactable)null);
			}
			List<Interactable> spawnedInteractables = desk.spawnedInteractables;
			if (spawnedInteractables == null)
			{
				return;
			}
			for (int num = spawnedInteractables.Count - 1; num >= 0; num--)
			{
				Interactable val5 = spawnedInteractables[num];
				if ((SoCustomComparison)(object)((val5 != null) ? val5.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)val5.preset).presetName == "NamePlacard" && (Object)(object)val5.belongsTo != (Object)null && ((Il2CppObjectBase)val5.belongsTo).Pointer == ((Il2CppObjectBase)instance).Pointer)
				{
					val5.SafeDelete(false);
				}
			}
		}

		private static FurnitureLocation? Drawers(NewAddress office, FurnitureLocation desk)
		{
			FurnitureLocation val = Find(office, desk.id + 1);
			if (!((SoCustomComparison)(object)((val != null) ? val.furniture : null) != (SoCustomComparison)null) || !((Object)val.furniture).name.Contains("Drawers"))
			{
				return null;
			}
			return val;
		}

		private static Interactable? WorkSpot(FurnitureLocation desk)
		{
			List<Interactable> integratedInteractables = desk.integratedInteractables;
			if (integratedInteractables == null)
			{
				return null;
			}
			Enumerator<Interactable> enumerator = integratedInteractables.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Interactable current = enumerator.Current;
				if ((SoCustomComparison)(object)((current != null) ? current.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)current.preset).presetName == ((Object)desk.furniture).name)
				{
					return current;
				}
			}
			if (integratedInteractables.Count <= 0)
			{
				return null;
			}
			return integratedInteractables[0];
		}

		private static void Own(NewAddress office, FurnitureLocation f, OwnershipClass cls, Human who, bool own)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> furnitureBelongsTo = ((NewGameLocation)office).furnitureBelongsTo;
			if (furnitureBelongsTo != null)
			{
				OwnInMap(furnitureBelongsTo, f, cls, who, own);
			}
			List<Interactable> integratedInteractables = f.integratedInteractables;
			if (integratedInteractables == null)
			{
				return;
			}
			Enumerator<Interactable> enumerator = integratedInteractables.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Interactable current = enumerator.Current;
				if (!((SoCustomComparison)(object)((current != null) ? current.preset : null) == (SoCustomComparison)null) && !((SoCustomComparison)current.preset).presetName.Contains("Cruncher"))
				{
					if (own && (Object)(object)current.belongsTo == (Object)null)
					{
						current.belongsTo = who;
					}
					else if (!own && (Object)(object)current.belongsTo != (Object)null && ((Il2CppObjectBase)current.belongsTo).Pointer == ((Il2CppObjectBase)who).Pointer)
					{
						current.belongsTo = null;
					}
				}
			}
		}

		private static void OwnInMap(Dictionary<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> belongs, FurnitureLocation f, OwnershipClass cls, Human who, bool own)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<FurnitureLocation, List<Human>> val = default(Dictionary<FurnitureLocation, List<Human>>);
			if (!belongs.TryGetValue(cls, ref val) || val == null)
			{
				if (!own)
				{
					return;
				}
				val = (belongs[cls] = new Dictionary<FurnitureLocation, List<Human>>());
			}
			List<Human> val3 = default(List<Human>);
			if (!val.TryGetValue(f, ref val3) || val3 == null)
			{
				if (!own)
				{
					return;
				}
				val3 = (val[f] = new List<Human>());
			}
			bool flag = false;
			Enumerator<Human> enumerator = val3.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Human current = enumerator.Current;
				if ((Object)(object)current != (Object)null && ((Il2CppObjectBase)current).Pointer == ((Il2CppObjectBase)who).Pointer)
				{
					flag = true;
				}
			}
			if (own && !flag)
			{
				val3.Add(who);
			}
			if (!(!own && flag))
			{
				return;
			}
			for (int num = val3.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)val3[num] != (Object)null && ((Il2CppObjectBase)val3[num]).Pointer == ((Il2CppObjectBase)who).Pointer)
				{
					val3.RemoveAt(num);
				}
			}
		}

		private static IEnumerable<FurnitureLocation> Furniture(NewAddress office)
		{
			if (((NewGameLocation)office).rooms == null)
			{
				yield break;
			}
			Enumerator<NewRoom> enumerator = ((NewGameLocation)office).rooms.GetEnumerator();
			while (enumerator.MoveNext())
			{
				NewRoom current = enumerator.Current;
				if (((current != null) ? current.individualFurniture : null) == null)
				{
					continue;
				}
				Enumerator<FurnitureLocation> enumerator2 = current.individualFurniture.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					FurnitureLocation current2 = enumerator2.Current;
					if ((SoCustomComparison)(object)((current2 != null) ? current2.furniture : null) != (SoCustomComparison)null)
					{
						yield return current2;
					}
				}
			}
		}
	}
	public static class Discipline
	{
		public static int Strikes { get; private set; }

		public static float LastStrikeAt { get; private set; } = -1f;

		public static float ProbationUntil { get; private set; } = -1f;

		public static int Deduction { get; set; }

		public static bool OnProbation
		{
			get
			{
				if ((Object)(object)SessionData.Instance != (Object)null)
				{
					return SessionData.Instance.gameTime < ProbationUntil;
				}
				return false;
			}
		}

		public static void Load(int strikes, float last, float probation, int deduction)
		{
			Strikes = strikes;
			LastStrikeAt = last;
			ProbationUntil = probation;
			Deduction = deduction;
		}

		public static void Reset()
		{
			Load(0, -1f, -1f, 0);
		}

		public static void Strike(string subject, string what)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			if (Employment.Employed)
			{
				float gameTime = SessionData.Instance.gameTime;
				Strikes++;
				LastStrikeAt = gameTime;
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(22, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[discipline] strike ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Strikes);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(subject);
				}
				log.LogInfo(val);
				string text;
				switch (Strikes)
				{
				case 1:
					text = "Consider this a warning.";
					break;
				case 2:
				{
					int num = (int)(Payroll.PerShift() * Plugin.Cfg.DockShifts.Value);
					Deduction += num;
					text = $"Cr {num} will come out of your next pay.";
					break;
				}
				case 3:
					ProbationUntil = gameTime + 24f * Plugin.Cfg.ProbationDays.Value;
					Reports.Expect(Reports.Kind.Paperwork, "Disciplinary paperwork", gameTime);
					text = $"You're on probation for {Plugin.Cfg.ProbationDays.Value:0} days: your warrant requests go to the bottom of the pile, " + "and the uniforms have been told to keep you at arm's length. You also have paperwork to catch up on.";
					break;
				default:
					text = "That's the last one. You're dismissed. Hand in your badge at the front desk on your way out.";
					break;
				}
				Captain.Memo(subject, "|receiver.casualname|, " + what + " " + text);
				if (Strikes >= 4)
				{
					Employment.Dismiss();
				}
			}
		}

		public static void Tick()
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			if (!Employment.Employed || Strikes <= 0)
			{
				return;
			}
			float gameTime = SessionData.Instance.gameTime;
			if (LastStrikeAt >= 0f && gameTime - LastStrikeAt >= 24f * Plugin.Cfg.CoolDays.Value)
			{
				Strikes--;
				LastStrikeAt = gameTime;
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(46, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[discipline] a clean stretch: strikes down to ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Strikes);
				}
				log.LogInfo(val);
			}
		}

		public static int TakeDeduction(int amount)
		{
			int num = Math.Min(amount, Deduction);
			Deduction -= num;
			return num;
		}
	}
	public static class Employment
	{
		private const string OfficePreset = "EnforcerOffice";

		private static readonly Random Dice = new Random();

		private static float _nextCheck;

		private const string JobName = "Detective";

		private const int JobId = 990001;

		private static NewAddress? _granted;

		public static int DivisionAddressId { get; private set; } = -1;

		public static int DeskId { get; private set; } = -1;

		public static float ApplicationAt { get; private set; } = -1f;

		public static bool Employed
		{
			get
			{
				if (Plugin.Cfg.OnTheForce.Value)
				{
					return DivisionAddressId >= 0;
				}
				return false;
			}
		}

		public static bool AutoHire
		{
			get
			{
				if (Plugin.Cfg.OnTheForce.Value)
				{
					return !Plugin.Cfg.HireInGame.Value;
				}
				return false;
			}
		}

		public static bool Applied => ApplicationAt >= 0f;

		public static Company? Division
		{
			get
			{
				CityData instance = CityData.Instance;
				Dictionary<int, NewAddress> val = ((instance != null) ? instance.addressDictionary : null);
				NewAddress val2 = default(NewAddress);
				if (DivisionAddressId < 0 || val == null || !val.TryGetValue(DivisionAddressId, ref val2))
				{
					return null;
				}
				if (val2 == null)
				{
					return null;
				}
				return val2.company;
			}
		}

		public static bool IsOwn(NewAddress? address)
		{
			if ((Object)(object)address != (Object)null && DivisionAddressId >= 0)
			{
				return address.id == DivisionAddressId;
			}
			return false;
		}

		public static bool IsOffice(NewAddress? address)
		{
			if ((SoCustomComparison)(object)((address != null) ? address.addressPreset : null) != (SoCustomComparison)null && ((Object)address.addressPreset).name == "EnforcerOffice")
			{
				return address.company != null;
			}
			return false;
		}

		public static string Apply()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (Employed)
			{
				Company? division = Division;
				return "You already serve with " + ((division != null) ? division.name : null) + ".";
			}
			if (Applied)
			{
				return "Your application is already being reviewed.";
			}
			float value = Plugin.Cfg.ApplicationHours.Value;
			ApplicationAt = SessionData.Instance.gameTime + value;
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] applied, answer in ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(value, "0.#");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("h");
			}
			log.LogInfo(val);
			return $"Application filed. You'll hear back in about {Mathf.CeilToInt(value)} hours.";
		}

		public static void Dismiss()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Company division = Division;
			Leave();
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] dismissed from ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((division != null) ? division.name : null) ?? "the force");
			}
			log.LogInfo(val);
			Notify("You have been dismissed from " + (((division != null) ? division.name : null) ?? "the force") + ".", (Icon)29);
		}

		public static void Resign()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Company division = Division;
			Leave();
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] resigned from ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((division != null) ? division.name : null) ?? "the force");
			}
			log.LogInfo(val);
			Notify("You have resigned from " + (((division != null) ? division.name : null) ?? "the force") + ".", (Icon)29);
		}

		private static void Leave()
		{
			ReleaseDesk();
			Shifts.Reset();
			Reports.Reset();
			Payroll.Reset();
			Discipline.Reset();
			DivisionAddressId = -1;
			ApplicationAt = -1f;
			EnsureAuthority();
			EnsureRoster();
		}

		public static bool Join(NewAddress office)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			if (DivisionAddressId >= 0 || !IsOffice(office))
			{
				return false;
			}
			DivisionAddressId = office.id;
			ApplicationAt = -1f;
			EnsureAuthority();
			EnsureRoster();
			EnsureDesk();
			Human director = office.company.director;
			ManualLogSource log = Plugin.Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 3, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] you now serve in ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(office.company.name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (office ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)office).name);
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", floor ");
				NewFloor floor = ((NewGameLocation)office).floor;
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int?>((floor != null) ? new int?(floor.floor) : ((int?)null));
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
			}
			log.LogInfo(val);
			Notify("You've been assigned to " + office.company.name + (((Object)(object)director == (Object)null) ? "." : (". Report to Captain " + director.GetCitizenName() + ".")), (Icon)13);
			Human val2 = director ?? WarrantMail.Sender();
			if ((Object)(object)val2 != (Object)null)
			{
				string[] obj = new string[9]
				{
					"|receiver.name|, your application has been approved. You are assigned to ",
					office.company.name,
					" as a detective. ",
					((Object)(object)director == (Object)null) ? "" : ("Report to Captain " + director.GetCitizenName() + " "),
					null,
					null,
					null,
					null,
					null
				};
				DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(35, 2);
				defaultInterpolatedStringHandler.AppendLiteral("at the ");
				defaultInterpolatedStringHandler.AppendFormatted(office.company.name);
				defaultInterpolatedStringHandler.AppendLiteral(" office, City Hall, floor ");
				NewFloor floor2 = ((NewGameLocation)office).floor;
				defaultInterpolatedStringHandler.AppendFormatted((floor2 != null) ? new int?(floor2.floor) : ((int?)null));
				defaultInterpolatedStringHandler.AppendLiteral(". ");
				obj[4] = defaultInterpolatedStringHandler.ToStringAndClear();
				string text = DeskRoom();
				obj[5] = ((text != null) ? ("Your desk is waiting for you in the " + text + ". ") : "");
				obj[6] = "Your shifts are ";
				obj[7] = Shifts.ScheduleText();
				obj[8] = ". Sign in at a division cruncher when each one starts. You have an account on the division's crunchers, and our premises are open to you at any hour.";
				WarrantMail.Letter(val2, string.Concat(obj), "WELCOME TO " + office.company.name.ToUpperInvariant(), "City Hall personnel office.", "welcome letter from " + office.company.name);
			}
			return true;
		}

		private static void Decide()
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			ApplicationAt = -1f;
			List<NewAddress> list = new List<NewAddress>();
			List<NewAddress> list2 = new List<NewAddress>();
			CityData instance = CityData.Instance;
			Dictionary<int, NewAddress> val = ((instance != null) ? instance.addressDictionary : null);
			if (val != null)
			{
				Enumerator<int, NewAddress> enumerator = val.GetEnumerator();
				bool flag = default(bool);
				while (enumerator.MoveNext())
				{
					KeyValuePair<int, NewAddress> current = enumerator.Current;
					if (!IsOffice(current.Value))
					{
						continue;
					}
					list.Add(current.Value);
					int count = Desks.Free(current.Value).Count;
					if (count > 0)
					{
						list2.Add(current.Value);
					}
					if (Plugin.Cfg.DebugLogging.Value)
					{
						ManualLogSource log = Plugin.Log;
						BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(33, 4, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[job] ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(current.Value.company.name);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)current.Value).name);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("): ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Desks.All(current.Value).Count);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" work positions, ");
							((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(count);
							((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" free");
						}
						log.LogInfo(val2);
					}
				}
			}
			if (list.Count == 0)
			{
				Plugin.Log.LogWarning((object)"[job] no enforcer divisions in this city");
				Notify("Your application was lost. Try again.", (Icon)29);
			}
			else
			{
				List<NewAddress> list3 = ((list2.Count > 0) ? list2 : list);
				Join(list3[Dice.Next(list3.Count)]);
			}
		}

		private static void Notify(string text, Icon icon)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Lib.GameMessage.Broadcast(text, (GameMessageType)0, icon, (Color?)null, 0f);
		}

		public static void Load(int addressId, float applicationAt, int deskId)
		{
			DivisionAddressId = addressId;
			ApplicationAt = applicationAt;
			DeskId = deskId;
			EnsureAuthority();
			EnsureRoster();
			EnsureDesk();
		}

		public static void Reset()
		{
			DivisionAddressId = -1;
			ApplicationAt = -1f;
			DeskId = -1;
		}

		public static void Tick()
		{
			if (!(Time.unscaledTime < _nextCheck))
			{
				_nextCheck = Time.unscaledTime + 5f;
				SessionData instance = SessionData.Instance;
				if (Applied && (Object)(object)instance != (Object)null && instance.gameTime >= ApplicationAt)
				{
					Decide();
				}
				EnsureAuthority();
				EnsureRoster();
				EnsureDesk();
			}
		}

		public static void EnsureAuthority()
		{
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				Player instance = Player.Instance;
				HashSet<NewGameLocation> val = ((instance != null) ? ((Actor)instance).locationsOfAuthority : null);
				if ((Object)(object)instance == (Object)null || val == null)
				{
					return;
				}
				NewAddress val2 = null;
				CityData instance2 = CityData.Instance;
				Dictionary<int, NewAddress> val3 = ((instance2 != null) ? instance2.addressDictionary : null);
				if (Employed)
				{
					val3?.TryGetValue(DivisionAddressId, ref val2);
				}
				if ((Object)(object)_granted != (Object)null && ((Object)(object)val2 == (Object)null || ((Il2CppObjectBase)_granted).Pointer != ((Il2CppObjectBase)val2).Pointer))
				{
					val.Remove((NewGameLocation)(object)_granted);
					if (Plugin.Cfg.DebugLogging.Value)
					{
						ManualLogSource log = Plugin.Log;
						BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[job] authority removed: ");
							((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)_granted).name);
						}
						log.LogInfo(val4);
					}
					_granted = null;
				}
				if ((Object)(object)val2 == (Object)null || val.Contains((NewGameLocation)(object)val2))
				{
					if (_granted == null)
					{
						_granted = val2;
					}
					return;
				}
				val.Add((NewGameLocation)(object)val2);
				_granted = val2;
				if (Plugin.Cfg.DebugLogging.Value)
				{
					ManualLogSource log2 = Plugin.Log;
					BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[job] authority granted: ");
						((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)val2).name);
					}
					log2.LogInfo(val4);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(36, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[job] could not set your authority: ");
					((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ex.Message);
				}
				log3.LogError(val5);
			}
		}

		private static NewAddress? Office()
		{
			CityData instance = CityData.Instance;
			Dictionary<int, NewAddress> val = ((instance != null) ? instance.addressDictionary : null);
			NewAddress result = default(NewAddress);
			if (!Employed || val == null || !val.TryGetValue(DivisionAddressId, ref result))
			{
				return null;
			}
			return result;
		}

		public static void EnsureDesk()
		{
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				NewAddress val = Office();
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Player instance = Player.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					Desks.EnsurePhoto(val, (Human)(object)instance);
				}
				FurnitureLocation val2 = ((DeskId >= 0) ? Desks.Find(val, DeskId) : null);
				if (val2 == null)
				{
					List<FurnitureLocation> list = Desks.Free(val);
					BepInExInfoLogInterpolatedStringHandler val3;
					if (list.Count == 0)
					{
						if (DeskId != -2)
						{
							ManualLogSource log = Plugin.Log;
							val3 = new BepInExInfoLogInterpolatedStringHandler(22, 1, ref flag);
							if (flag)
							{
								((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[job] no free desk in ");
								BepInExInfoLogInterpolatedStringHandler obj = val3;
								Company company = val.company;
								((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((company != null) ? company.name : null);
							}
							log.LogInfo(val3);
						}
						DeskId = -2;
						return;
					}
					list.Sort((FurnitureLocation a, FurnitureLocation b) => a.id.CompareTo(b.id));
					val2 = list[0];
					DeskId = val2.id;
					ManualLogSource log2 = Plugin.Log;
					val3 = new BepInExInfoLogInterpolatedStringHandler(23, 3, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[job] your desk: ");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)val2.furniture).name);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" #");
						((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(val2.id);
						((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" in ");
						BepInExInfoLogInterpolatedStringHandler obj2 = val3;
						NewNode anchorNode = val2.anchorNode;
						object obj3;
						if (anchorNode == null)
						{
							obj3 = null;
						}
						else
						{
							NewRoom room = anchorNode.room;
							obj3 = ((room != null) ? room.name : null);
						}
						((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((string)obj3);
					}
					log2.LogInfo(val3);
				}
				Desks.Claim(val, val2);
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Plugin.Log;
				BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(34, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[job] could not set up your desk: ");
					((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(ex.Message);
				}
				log3.LogError(val4);
			}
		}

		private static void ReleaseDesk()
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			try
			{
				NewAddress val = Office();
				FurnitureLocation val2 = (((Object)(object)val != (Object)null && DeskId >= 0) ? Desks.Find(val, DeskId) : null);
				if ((Object)(object)val != (Object)null && val2 != null)
				{
					Desks.Release(val, val2);
				}
				if ((Object)(object)val != (Object)null && (Object)(object)Player.Instance != (Object)null)
				{
					Desks.RemovePhoto(val, (Human)(object)Player.Instance);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[job] could not clear your desk: ");
					((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message);
				}
				log.LogError(val3);
			}
			DeskId = -1;
		}

		private static string? DeskRoom()
		{
			NewAddress val = Office();
			FurnitureLocation? obj = (((Object)(object)val != (Object)null && DeskId >= 0) ? Desks.Find(val, DeskId) : null);
			object obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				NewNode anchorNode = obj.anchorNode;
				if (anchorNode == null)
				{
					obj2 = null;
				}
				else
				{
					NewRoom room = anchorNode.room;
					obj2 = ((room != null) ? room.name : null);
				}
			}
			string text = (string)obj2;
			if (text == null)
			{
				return null;
			}
			Company company = val.company;
			string text2 = ((company != null) ? company.name : null) ?? "";
			if (text2.Length <= 0 || !text.StartsWith(text2))
			{
				return text;
			}
			return text.Substring(text2.Length).Trim() + " room";
		}

		public static void EnsureRoster()
		{
			//IL_0594: Unknown result type (might be due to invalid IL or missing references)
			//IL_059b: Expected O, but got Unknown
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0545: Expected O, but got Unknown
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0260: Unknown result type (might be due to invalid IL or missing references)
			//IL_028f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0326: Expected O, but got Unknown
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Expected O, but got Unknown
			bool flag = default(bool);
			try
			{
				Player instance = Player.Instance;
				if ((Object)(object)instance == (Object)null)
				{
					return;
				}
				Company val = (Employed ? Division : null);
				Occupation val2 = null;
				CityData instance2 = CityData.Instance;
				Dictionary<int, NewAddress> val3 = ((instance2 != null) ? instance2.addressDictionary : null);
				if (val3 != null)
				{
					Enumerator<int, NewAddress> enumerator = val3.GetEnumerator();
					while (enumerator.MoveNext())
					{
						KeyValuePair<int, NewAddress> current = enumerator.Current;
						NewAddress value = current.Value;
						object obj;
						if (value == null)
						{
							obj = null;
						}
						else
						{
							Company company = value.company;
							obj = ((company != null) ? company.companyRoster : null);
						}
						List<Occupation> val4 = (List<Occupation>)obj;
						if (val4 == null || !IsOffice(current.Value))
						{
							continue;
						}
						for (int num = val4.Count - 1; num >= 0; num--)
						{
							Occupation val5 = val4[num];
							if (val5 != null && !(val5.name != "Detective"))
							{
								if (val != null && ((Il2CppObjectBase)current.Value.company).Pointer == ((Il2CppObjectBase)val).Pointer && val2 == null)
								{
									val2 = val5;
								}
								else
								{
									val4.RemoveAt(num);
									if (Plugin.Cfg.DebugLogging.Value)
									{
										ManualLogSource log = Plugin.Log;
										BepInExInfoLogInterpolatedStringHandler val6 = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag);
										if (flag)
										{
											((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[job] removed your position from ");
											((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(current.Value.company.name);
										}
										log.LogInfo(val6);
									}
								}
							}
						}
					}
				}
				if (val == null)
				{
					if (((Human)instance).job != null && ((Human)instance).job.name == "Detective")
					{
						((Human)instance).job = null;
					}
					return;
				}
				if (val2 == null)
				{
					Occupation val7 = RankAndFile(val);
					val2 = new Occupation
					{
						id = 990001,
						name = "Detective",
						employer = val,
						preset = ((val7 != null) ? val7.preset : null),
						boss = (((val7 != null) ? val7.boss : null) ?? CaptainOf(val)),
						paygrade = ((val7 != null) ? val7.paygrade : 0f),
						teamID = ((val7 != null) ? val7.teamID : 0),
						work = (workType)((val7 != null) ? ((int)val7.work) : 0),
						tags = ((val7 != null) ? val7.tags : null),
						shift = ((val7 != null) ? val7.shift : null),
						workHours = Mathf.Repeat(Plugin.Cfg.ShiftEnd.Value - Plugin.Cfg.ShiftStart.Value, 24f),
						startTimeDecimalHour = Plugin.Cfg.ShiftStart.Value,
						endTimeDecialHour = Plugin.Cfg.ShiftEnd.Value,
						lunchBreak = (val7 != null && val7.lunchBreak),
						lunchBreakHoursAfterStart = ((val7 != null) ? val7.lunchBreakHoursAfterStart : 4f),
						workDaysList = Shifts.WorkDayList(),
						salary = ((val7 != null) ? val7.salary : 0f),
						salaryString = (((val7 != null) ? val7.salaryString : null) ?? "")
					};
					val.companyRoster.Add(val2);
					if (Plugin.Cfg.DebugLogging.Value)
					{
						ManualLogSource log2 = Plugin.Log;
						BepInExInfoLogInterpolatedStringHandler val6 = new BepInExInfoLogInterpolatedStringHandler(47, 4, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[job] added your position to ");
							((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(val.name);
							((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" ");
							((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("(modelled on ");
							BepInExInfoLogInterpolatedStringHandler obj2 = val6;
							object obj3;
							if (val7 == null)
							{
								obj3 = null;
							}
							else
							{
								Human employee = val7.employee;
								obj3 = ((employee != null) ? employee.GetCitizenName() : null);
							}
							if (obj3 == null)
							{
								obj3 = "nobody";
							}
							((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((string)obj3);
							((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(", ");
							((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(val2.startTimeDecimalHour, "0.#");
							((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("-");
							((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(val2.endTimeDecialHour, "0.#");
							((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(")");
						}
						log2.LogInfo(val6);
					}
				}
				if (Math.Abs(val2.startTimeDecimalHour - Plugin.Cfg.ShiftStart.Value) > 0.01f || Math.Abs(val2.endTimeDecialHour - Plugin.Cfg.ShiftEnd.Value) > 0.01f || val2.workDaysList == null || val2.workDaysList.Count != Shifts.WorkDayList().Count)
				{
					val2.startTimeDecimalHour = Plugin.Cfg.ShiftStart.Value;
					val2.endTimeDecialHour = Plugin.Cfg.ShiftEnd.Value;
					val2.workHours = Mathf.Repeat(Plugin.Cfg.ShiftEnd.Value - Plugin.Cfg.ShiftStart.Value, 24f);
					val2.workDaysList = Shifts.WorkDayList();
				}
				if ((Object)(object)val2.employee == (Object)null || ((Il2CppObjectBase)val2.employee).Pointer != ((Il2CppObjectBase)instance).Pointer || ((Human)instance).job == null || ((Il2CppObjectBase)((Human)instance).job).Pointer != ((Il2CppObjectBase)val2).Pointer)
				{
					val2.employee = (Human)(object)instance;
					((Human)instance).job = val2;
					if (Plugin.Cfg.DebugLogging.Value)
					{
						ManualLogSource log3 = Plugin.Log;
						BepInExInfoLogInterpolatedStringHandler val6 = new BepInExInfoLogInterpolatedStringHandler(32, 2, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[job] you hold the ");
							((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>("Detective");
							((BepInExLogInterpolatedStringHandler)val6).Appe