Decompiled source of Nivalis Unofficial Patch v0.3.61

BepInEx/plugins/NivalisUnofficialPatch/NivalisUnofficialPatch.dll

Decompiled a day ago
using System;
using System.Buffers.Binary;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.Json;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using CrazyMinnow.SALSA;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using Funly.SkyStudio;
using HarmonyLib;
using Hvizeu.NivalisMods;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.MethodInfo;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using MagicaCloth;
using Microsoft.CodeAnalysis;
using MonoMod.RuntimeDetour;
using Nivalis;
using Nivalis.CraftingSystem;
using Nivalis.DayNightCycle;
using Nivalis.Dialogue;
using Nivalis.Economy;
using Nivalis.GhostSystem;
using Nivalis.GhostSystem.Ai;
using Nivalis.GhostSystem.CustomerLoop;
using Nivalis.InventorySystem;
using Nivalis.Locale;
using Nivalis.Locale.UI;
using Nivalis.Localization;
using Nivalis.Player;
using Nivalis.SkillSystem;
using Nivalis.UI;
using Nivalis.UI.Concrete;
using Nivalis.UI.Greenhouse;
using Nivalis.UI.InGameMenu;
using Nivalis.UI.MinMaxSlider;
using Nivalis.Utility;
using Nivalis.Weather;
using NivalisUnofficialPatch.Core;
using NivalisUnofficialPatch.Hauling;
using RootMotion.FinalIK;
using TMPro;
using TheraBytes.BetterUi;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
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("Hvizeu")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.61.0")]
[assembly: AssemblyInformationalVersion("0.3.61")]
[assembly: AssemblyProduct("NivalisUnofficialPatch")]
[assembly: AssemblyTitle("NivalisUnofficialPatch")]
[assembly: AssemblyMetadata("PrivateDiagnosticsBuild", "false")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.61.0")]
[module: UnverifiableCode]
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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NativeIntegerAttribute : Attribute
	{
		public readonly bool[] TransformFlags;

		public NativeIntegerAttribute()
		{
			TransformFlags = new bool[1] { true };
		}

		public NativeIntegerAttribute(bool[] P_0)
		{
			TransformFlags = P_0;
		}
	}
}
namespace Hvizeu.NivalisMods
{
	internal static class CharacterClearance
	{
		internal static void Volume(Character character, out Vector3 lower, out Vector3 upper, out float radius)
		{
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: 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)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			Collider collide = character.Collide;
			CapsuleCollider val = ((collide != null) ? ((Il2CppObjectBase)collide).TryCast<CapsuleCollider>() : null);
			Vector3 val2;
			float num;
			if ((Object)(object)val != (Object)null && val.direction == 1)
			{
				Vector3 lossyScale = ((Component)val).transform.lossyScale;
				val2 = ((Component)val).transform.TransformPoint(val.center);
				radius = val.radius * Mathf.Max(Mathf.Abs(lossyScale.x), Mathf.Abs(lossyScale.z));
				num = val.height * Mathf.Abs(lossyScale.y);
			}
			else
			{
				if ((Object)(object)collide != (Object)null && collide.enabled)
				{
					Bounds bounds = collide.bounds;
					Vector3 size = ((Bounds)(ref bounds)).size;
					if (((Vector3)(ref size)).sqrMagnitude > 0.01f)
					{
						Bounds bounds2 = collide.bounds;
						val2 = ((Bounds)(ref bounds2)).center;
						radius = Mathf.Max(((Bounds)(ref bounds2)).extents.x, ((Bounds)(ref bounds2)).extents.z);
						num = ((Bounds)(ref bounds2)).size.y;
						goto IL_013a;
					}
				}
				NavMeshAgent agent = character.Movement.Agent;
				radius = agent.radius;
				num = agent.height;
				val2 = ((BaseCharacter)character).ThisTransform.position + Vector3.up * (num * 0.5f + agent.baseOffset);
			}
			goto IL_013a;
			IL_013a:
			radius = Mathf.Max(0.1f, radius);
			float num2 = Mathf.Max(0f, num * 0.5f - radius);
			lower = val2 - Vector3.up * num2;
			upper = val2 + Vector3.up * num2;
		}

		internal static bool Blocks(Character character, Collider collider)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			Character componentInParent = ((Component)collider).GetComponentInParent<Character>();
			if ((Object)(object)componentInParent != (Object)null)
			{
				return ((Il2CppObjectBase)componentInParent).Pointer != ((Il2CppObjectBase)character).Pointer;
			}
			Collider collide = character.Collide;
			if ((Object)(object)collide == (Object)null)
			{
				return true;
			}
			int layer = ((Component)collider).gameObject.layer;
			if (Singleton<CharacterManager>.InstanceExist() && (LayerMask.op_Implicit(Singleton<CharacterManager>.Instance.EnvironmentLayer) & (1 << layer)) != 0)
			{
				return true;
			}
			return !Physics.GetIgnoreLayerCollision(((Component)collide).gameObject.layer, layer);
		}
	}
}
namespace NivalisUnofficialPatch
{
	[HarmonyPatch(typeof(Character), "DoLateUpdate")]
	internal static class AnimationLodPatch
	{
		private static bool failed;

		private static bool Prepare()
		{
			return PerformanceCompatibility.Owns(PerformanceFeature.Animation);
		}

		private static void Prefix(Character __instance, out int __state)
		{
			__state = 0;
			if (failed || !PerformanceCompatibility.Owns(PerformanceFeature.Animation))
			{
				return;
			}
			try
			{
				float value = RenderingOptions.AnimationLodReduction.Value;
				if (!(value <= 0f) && __instance.AnimatorUpdateStep <= 0 && ((BaseCharacter)__instance).CameraVisible)
				{
					__state = AnimationLodPolicy.Step(((BaseCharacter)__instance).SqrVisibleDistance, value);
				}
			}
			catch (Exception ex)
			{
				failed = true;
				PerformanceCompatibility.Health(PerformanceFeature.Animation, ex.Message);
				ModFaults.Report("Animation cadence (disabled for session)", ex);
			}
		}

		private static void Postfix(Character __instance, int __state)
		{
			try
			{
				if (__state > 0 && !failed)
				{
					__instance.AnimatorUpdateStep = RuntimePerformance.Stagger(__instance, __state);
				}
			}
			catch (Exception ex)
			{
				failed = true;
				PerformanceCompatibility.Health(PerformanceFeature.Animation, ex.Message);
				ModFaults.Report("Animation cadence (disabled for session)", ex);
			}
		}
	}
	internal static class AvaVoice
	{
		private sealed record VoiceSource(AudioSource Source, bool OriginalMute);

		internal const string PersonGuid = "7aa86416-295d-40ad-a22b-3eb7a32c638f";

		private static readonly Dictionary<int, VoiceSource> Sources = new Dictionary<int, VoiceSource>();

		private static AudioSource? phoneSource;

		internal static bool Enabled;

		internal static AudioSource? CharacterSource(CharacterCommunication character)
		{
			if (!((Object)(object)character != (Object)null) || !((Object)(object)character.Salsa != (Object)null))
			{
				return null;
			}
			return character.Salsa.audioSrc;
		}

		internal static void BeginPhone(NewPageShownArgs line)
		{
			AudioSource inEarVOSource = AudioHandler.InEarVOSource;
			if ((Object)(object)phoneSource != (Object)(object)inEarVOSource)
			{
				Release(phoneSource);
			}
			phoneSource = inEarVOSource;
			Begin(inEarVOSource, line, line != null && line.isPhoneCall);
		}

		internal static void ReleasePhone()
		{
			Release(phoneSource);
			phoneSource = null;
		}

		internal static void Begin(AudioSource? source, NewPageShownArgs? line, bool audiblePath = true)
		{
			if ((Object)(object)source == (Object)null)
			{
				return;
			}
			KeyValuePair<int, VoiceSource>[] array = Sources.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<int, VoiceSource> keyValuePair = array[i];
				if ((Object)(object)keyValuePair.Value.Source == (Object)null)
				{
					Sources.Remove(keyValuePair.Key);
				}
			}
			object obj;
			if (line == null)
			{
				obj = null;
			}
			else
			{
				DialogueStepDisplayData dialogue = line.dialogue;
				obj = ((dialogue != null) ? dialogue.Speaker : null);
			}
			Person val = (Person)obj;
			if (!audiblePath || !((Object)(object)val != (Object)null) || !string.Equals(val.Guid, "7aa86416-295d-40ad-a22b-3eb7a32c638f", StringComparison.OrdinalIgnoreCase))
			{
				Release(source);
				return;
			}
			int instanceID = ((Object)source).GetInstanceID();
			if (!Sources.TryGetValue(instanceID, out VoiceSource value))
			{
				Sources.Add(instanceID, value = new VoiceSource(source, source.mute));
			}
			source.mute = value.OriginalMute || Enabled;
		}

		internal static void Apply(bool enabled)
		{
			Enabled = enabled;
			KeyValuePair<int, VoiceSource>[] array = Sources.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<int, VoiceSource> keyValuePair = array[i];
				if ((Object)(object)keyValuePair.Value.Source == (Object)null)
				{
					Sources.Remove(keyValuePair.Key);
				}
				else
				{
					keyValuePair.Value.Source.mute = keyValuePair.Value.OriginalMute || enabled;
				}
			}
		}

		internal static void Release(AudioSource? source)
		{
			if ((Object)(object)source != (Object)null && Sources.Remove(((Object)source).GetInstanceID(), out VoiceSource value))
			{
				source.mute = value.OriginalMute;
			}
		}

		internal static void Clear()
		{
			foreach (VoiceSource value in Sources.Values)
			{
				if ((Object)(object)value.Source != (Object)null)
				{
					value.Source.mute = value.OriginalMute;
				}
			}
			Sources.Clear();
			phoneSource = null;
		}
	}
	[HarmonyPatch(typeof(DialoguePhoneAudioPlayer), "OnNewDialogueLine")]
	internal static class AvaPhoneVoicePatch
	{
		internal static void Prefix(NewPageShownArgs obj)
		{
			AvaVoice.BeginPhone(obj);
		}
	}
	[HarmonyPatch(typeof(DialoguePhoneAudioPlayer), "OnDialogueEnd")]
	internal static class AvaPhoneVoiceEndPatch
	{
		internal static void Postfix()
		{
			AvaVoice.ReleasePhone();
		}
	}
	[HarmonyPatch(typeof(DialoguePhoneAudioPlayer), "OnDestroy")]
	internal static class AvaPhoneVoiceDestroyPatch
	{
		internal static void Prefix()
		{
			AvaVoice.ReleasePhone();
		}
	}
	[HarmonyPatch(typeof(CharacterCommunication), "StartTalk")]
	internal static class AvaCharacterVoicePatch
	{
		internal static void Prefix(CharacterCommunication __instance, NewPageShownArgs lineArgs)
		{
			AvaVoice.Begin(AvaVoice.CharacterSource(__instance), lineArgs);
		}
	}
	[HarmonyPatch(typeof(CharacterCommunication), "OnPostRelease")]
	internal static class AvaCharacterVoiceReleasePatch
	{
		internal static void Postfix(CharacterCommunication __instance)
		{
			AvaVoice.Release(AvaVoice.CharacterSource(__instance));
		}
	}
	internal static class BalancedDetailOptimizations
	{
		private sealed class ChangedLod
		{
			internal LODGroup Group;

			internal LOD[] Original;
		}

		private static readonly Dictionary<int, ChangedLod> lods = new Dictionary<int, ChangedLod>();

		private static readonly Dictionary<int, BaseCloth> cloth = new Dictionary<int, BaseCloth>();

		private static readonly List<int> retired = new List<int>();

		internal static int LodCount => lods.Count;

		internal static int ClothCount => cloth.Count;

		internal static void Inspect(LODGroup group)
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			if (!RenderingOptions.BalancedDetailEnabled || (Object)(object)group == (Object)null || lods.ContainsKey(((Object)group).GetInstanceID()))
			{
				return;
			}
			LOD[] array = ((IEnumerable<LOD>)group.GetLODs()).ToArray();
			Character component = ((Component)group).GetComponent<Character>();
			bool flag = (Object)(object)component != (Object)null && (Object)(object)component.LODGroup == (Object)(object)group;
			if (!flag && array.Any((LOD l) => ((IEnumerable<Renderer>)l.renderers).Any((Renderer r) => (Object)(object)r == (Object)null || (Object)(object)((Il2CppObjectBase)r).TryCast<MeshRenderer>() == (Object)null)))
			{
				return;
			}
			Vector3 lossyScale = ((Component)group).transform.lossyScale;
			float worldSize = group.size * Math.Max(Math.Abs(lossyScale.x), Math.Max(Math.Abs(lossyScale.y), Math.Abs(lossyScale.z)));
			float[] heights = BalancedDetailPolicy.Heights(((Object)((Component)group).gameObject).name, worldSize, array.Select((LOD l) => l.screenRelativeTransitionHeight).ToArray(), flag, RenderingOptions.AppliedDetailStrength);
			if (heights != null)
			{
				LOD[] array2 = ((IEnumerable<LOD>)array).Select((Func<LOD, int, LOD>)((LOD l, int i) => new LOD(heights[i], Il2CppReferenceArray<Renderer>.op_Implicit(((IEnumerable<Renderer>)l.renderers).ToArray()))
				{
					fadeTransitionWidth = l.fadeTransitionWidth
				})).ToArray();
				lods.Add(((Object)group).GetInstanceID(), new ChangedLod
				{
					Group = group,
					Original = array
				});
				group.SetLODs(Il2CppReferenceArray<LOD>.op_Implicit(array2));
			}
		}

		internal static void Inspect(Character character)
		{
			if (!RenderingOptions.BalancedDetailEnabled || (Object)(object)character == (Object)null || character.magicaCloth == null)
			{
				return;
			}
			Enumerator<BaseCloth> enumerator = character.magicaCloth.GetEnumerator();
			while (enumerator.MoveNext())
			{
				BaseCloth current = enumerator.Current;
				if (!((Object)(object)current == (Object)null) && !cloth.ContainsKey(((Object)current).GetInstanceID()) && BalancedDetailPolicy.MissingClothLimit(((Object)((Component)character).gameObject).name, ((Object)((Component)current).gameObject).name, current.DistanceDisable_Active, current.DistanceDisable_Distance, current.DistanceDisable_FadeDistance))
				{
					cloth.Add(((Object)current).GetInstanceID(), current);
					current.DistanceDisable_Active = true;
				}
			}
		}

		internal static void Prune()
		{
			retired.Clear();
			foreach (KeyValuePair<int, ChangedLod> lod in lods)
			{
				if ((Object)(object)lod.Value.Group == (Object)null)
				{
					retired.Add(lod.Key);
				}
			}
			foreach (int item in retired)
			{
				lods.Remove(item);
			}
			retired.Clear();
			foreach (KeyValuePair<int, BaseCloth> item2 in cloth)
			{
				if ((Object)(object)item2.Value == (Object)null)
				{
					retired.Add(item2.Key);
				}
			}
			foreach (int item3 in retired)
			{
				cloth.Remove(item3);
			}
			retired.Clear();
		}

		internal static bool OwnsLod(int id)
		{
			return lods.ContainsKey(id);
		}

		internal static void Stop()
		{
			KeyValuePair<int, ChangedLod>[] array = lods.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<int, ChangedLod> entry = array[i];
				if (!DistantCharacterMeshes.OwnsLod(entry.Key) && RenderingOptimizations.TryRestore($"balanced LOD {entry.Key}", delegate
				{
					if ((Object)(object)entry.Value.Group != (Object)null)
					{
						entry.Value.Group.SetLODs(Il2CppReferenceArray<LOD>.op_Implicit(entry.Value.Original));
					}
				}))
				{
					lods.Remove(entry.Key);
				}
			}
			KeyValuePair<int, BaseCloth>[] array2 = cloth.ToArray();
			for (int i = 0; i < array2.Length; i++)
			{
				KeyValuePair<int, BaseCloth> entry2 = array2[i];
				if (RenderingOptimizations.TryRestore($"cloth {entry2.Key}", delegate
				{
					if ((Object)(object)entry2.Value != (Object)null)
					{
						entry2.Value.DistanceDisable_Active = false;
					}
				}))
				{
					cloth.Remove(entry2.Key);
				}
			}
		}
	}
	internal static class BusinessReminders
	{
		internal static ConfigEntry<bool> Hide;

		internal static void Bind(ConfigFile config)
		{
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Expected O, but got Unknown
			bool flag = true;
			string text = Path.Combine(Paths.ConfigPath, "hvizeu.nivalis.trackedquestshud.cfg");
			try
			{
				if (File.Exists(text) && new FileInfo(text).Length <= 65536)
				{
					string text2 = "";
					foreach (string item in File.ReadLines(text))
					{
						string text3 = item.Trim();
						if (text3.StartsWith('[') && text3.EndsWith(']'))
						{
							string text4 = text3;
							text2 = text4.Substring(1, text4.Length - 1 - 1);
						}
						if (!(text2 != "HUD"))
						{
							string[] array = text3.Split('=', 2);
							if (array.Length == 2 && array[0].Trim() == "HideBusinessReminders" && bool.TryParse(array[1].Trim(), out var result))
							{
								flag = result;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource modLog = Plugin.ModLog;
				bool flag2 = default(bool);
				BepInExWarningLogInterpolatedStringHandler val = new BepInExWarningLogInterpolatedStringHandler(53, 1, ref flag2);
				if (flag2)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Could not read retired HUD preference; default used: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(ex.Message);
				}
				modLog.LogWarning(val);
			}
			Hide = config.Bind<bool>("HUD", "HideBusinessReminders", flag, "Hide automatic business reminders on the HUD. Native quest filtering remains authoritative.");
		}
	}
	[HarmonyPatch(typeof(ActiveJournalEntriesUi), "Refresh")]
	internal static class BusinessReminderRefresh
	{
		private sealed class HiddenState
		{
			internal readonly List<GameObject> Rows = new List<GameObject>();

			internal float? Alpha;
		}

		private static readonly Dictionary<int, HiddenState> hidden = new Dictionary<int, HiddenState>();

		internal static void RefreshVisible()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			if (ApplicationState.IsQuitting)
			{
				return;
			}
			try
			{
				foreach (ActiveJournalEntriesUi item in Object.FindObjectsOfType<ActiveJournalEntriesUi>(true))
				{
					if ((Object)(object)item != (Object)null)
					{
						item.Refresh();
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource modLog = Plugin.ModLog;
				bool flag = default(bool);
				BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(34, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Business reminder refresh failed: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
				}
				modLog.LogError(val);
			}
		}

		internal static void RestoreVisible()
		{
			foreach (ActiveJournalEntriesUi item in Object.FindObjectsOfType<ActiveJournalEntriesUi>(true))
			{
				if ((Object)(object)item != (Object)null)
				{
					Prefix(item, __runOriginal: true);
				}
			}
			hidden.Clear();
		}

		internal static void Forget(ActiveJournalEntriesUi ui)
		{
			hidden.Remove(((Object)ui).GetInstanceID());
		}

		[HarmonyPrefix]
		internal static void Prefix(ActiveJournalEntriesUi __instance, bool __runOriginal)
		{
			if (!__runOriginal || !hidden.Remove(((Object)__instance).GetInstanceID(), out HiddenState value))
			{
				return;
			}
			foreach (GameObject row in value.Rows)
			{
				if ((Object)(object)row != (Object)null)
				{
					row.SetActive(true);
				}
			}
			float? alpha = value.Alpha;
			if (alpha.HasValue)
			{
				float valueOrDefault = alpha.GetValueOrDefault();
				if ((Object)(object)__instance.entriesGroup != (Object)null && __instance.entriesGroup.alpha == 0f)
				{
					__instance.entriesGroup.alpha = valueOrDefault;
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		internal static void Postfix(ActiveJournalEntriesUi __instance, bool __runOriginal)
		{
			if (!__runOriginal || ApplicationState.IsQuitting || !((UIPanel)__instance).IsVisible || !BusinessReminders.Hide.Value || (Object)(object)__instance.entriesGroup == (Object)null || (Object)(object)__instance.questList == (Object)null || (Object)(object)__instance.venueQuestList == (Object)null)
			{
				return;
			}
			HiddenState hiddenState = new HiddenState();
			ItemListUI venueQuestList = __instance.venueQuestList;
			for (int i = 0; i < venueQuestList.DisplayedCount; i++)
			{
				GameObject gameObject = venueQuestList.GetItem(i).GameObject;
				if (gameObject.activeSelf)
				{
					hiddenState.Rows.Add(gameObject);
					gameObject.SetActive(false);
				}
			}
			bool flag = false;
			for (int j = 0; j < __instance.questList.DisplayedCount; j++)
			{
				flag |= __instance.questList.GetItem(j).GameObject.activeSelf;
			}
			if (!flag && __instance.entriesGroup.alpha != 0f)
			{
				hiddenState.Alpha = __instance.entriesGroup.alpha;
				__instance.entriesGroup.alpha = 0f;
			}
			if (hiddenState.Rows.Count != 0 || hiddenState.Alpha.HasValue)
			{
				hidden[((Object)__instance).GetInstanceID()] = hiddenState;
				if (hiddenState.Rows.Count != 0)
				{
					LayoutRebuilder.ForceRebuildLayoutImmediate(__instance.entryParent);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ActiveJournalEntriesUi), "ShowAnimated")]
	internal static class BusinessReminderShow
	{
		private static void Postfix(ActiveJournalEntriesUi __instance)
		{
			if (!ApplicationState.IsQuitting && ((UIPanel)__instance).IsVisible)
			{
				__instance.Refresh();
			}
		}
	}
	[HarmonyPatch(typeof(ActiveJournalEntriesUi), "OnDestroy")]
	internal static class BusinessReminderDestroy
	{
		private static void Prefix(ActiveJournalEntriesUi __instance)
		{
			BusinessReminderRefresh.Forget(__instance);
		}
	}
	[HarmonyPatch(typeof(CharacterMovement), "Side")]
	internal static class ChairExitPatch
	{
		internal static long Recovered;

		private static int unresolvedReports;

		private static bool Prefix(CharacterMovement __instance, TransitionType transition, ref float __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return ChooseExit(__instance, transition, ref __result);
			}
			catch (Exception error)
			{
				ModFaults.Report("Chair exit selection", error);
				return true;
			}
		}

		private static bool ChooseExit(CharacterMovement __instance, TransitionType transition, ref float __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030d: Expected O, but got Unknown
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: 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_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Expected O, but got Unknown
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			if ((int)transition != 1)
			{
				return true;
			}
			Character character = __instance.character;
			if ((Object)(object)character == (Object)null)
			{
				return true;
			}
			AISpot previousSpot = character.previousSpot;
			Il2CppArrayBase<AISlot> val = ((Spot<AISlot>)(object)previousSpot)?.points;
			NavMeshAgent agent = __instance.Agent;
			if ((Object)(object)previousSpot == (Object)null || val == null || (Object)(object)agent == (Object)null || !Singleton<CharacterManager>.InstanceExist())
			{
				return true;
			}
			Vector3 origin = ((Component)__instance).transform.position;
			int environment = LayerMask.op_Implicit(Singleton<CharacterManager>.Instance.EnvironmentLayer);
			string blocker = "unknown";
			NavMeshHit val3 = default(NavMeshHit);
			foreach (AISlot item in val)
			{
				if (item == null)
				{
					return true;
				}
				Vector3 val2 = CharacterUtils.TransformPointUnscaled(((Component)previousSpot).transform, ((Slot)item).position);
				if (NavMesh.SamplePosition(val2, ref val3, 0.2f, -1) && NativeClear(val2))
				{
					return true;
				}
			}
			string text = "no authored exit slots";
			NavMeshHit val5 = default(NavMeshHit);
			bool flag = default(bool);
			foreach (AISlot item2 in val)
			{
				Vector3 val4 = CharacterUtils.TransformPointUnscaled(((Component)previousSpot).transform, ((Slot)item2).position);
				if (!NavMesh.SamplePositionFilter(val4, ref val5, 0.45f, agent.agentTypeID, agent.areaMask))
				{
					text = "no matching NavMesh near authored exit";
					continue;
				}
				if (Mathf.Abs(((NavMeshHit)(ref val5)).position.y - val4.y) > 0.2f)
				{
					text = "authored exit projects to a different height";
					continue;
				}
				if (!NativeClear(val4))
				{
					text = "native exit sweep blocked by environment";
					continue;
				}
				if (((Component)previousSpot).transform.InverseTransformPoint(((NavMeshHit)(ref val5)).position).x <= 0f != ((Slot)item2).position.x <= 0f)
				{
					text = "NavMesh projects across the chair center";
					continue;
				}
				string text2 = SceneLifecyclePatches.ProjectionObstruction(__instance, origin, val4) ?? SceneLifecyclePatches.ProjectionObstruction(__instance, origin, ((NavMeshHit)(ref val5)).position);
				if (text2 != null)
				{
					text = text2;
					continue;
				}
				__result = ((((Slot)item2).position.x <= 0f) ? 1f : (-1f));
				Recovered++;
				if (Recovered <= 8)
				{
					ManualLogSource modLog = Plugin.ModLog;
					BepInExInfoLogInterpolatedStringHandler val6 = new BepInExInfoLogInterpolatedStringHandler(57, 3, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("Chair exit recovered: character=");
						((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(((Object)character).name);
						((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("; spot=");
						((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(((Object)previousSpot).name);
						((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("; navmeshOffset=");
						((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(Vector3.Distance(val4, ((NavMeshHit)(ref val5)).position), "F3");
						((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("m.");
					}
					modLog.LogInfo(val6);
				}
				return false;
			}
			if (unresolvedReports++ < 16)
			{
				ManualLogSource modLog2 = Plugin.ModLog;
				BepInExWarningLogInterpolatedStringHandler val7 = new BepInExWarningLogInterpolatedStringHandler(112, 6, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("Chair exit unresolved: character=");
					((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<string>(((Object)character).name);
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("; spot=");
					((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<string>(((Object)previousSpot).name);
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("; slots=");
					((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<int>(val.Length);
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("; position=");
					((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<Vector3>(origin);
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("; reason=");
					((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral("; sweepBlocker=");
					((BepInExLogInterpolatedStringHandler)val7).AppendFormatted<string>(blocker);
					((BepInExLogInterpolatedStringHandler)val7).AppendLiteral(". Native transition retained.");
				}
				modLog2.LogWarning(val7);
			}
			return true;
			bool NativeClear(Vector3 point)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				Vector3 val8 = origin + Vector3.up * 0.75f;
				Vector3 val9 = point - origin;
				RaycastHit val10 = default(RaycastHit);
				bool num = Physics.SphereCast(val8, 0.15f, ((Vector3)(ref val9)).normalized, ref val10, 0.6f, environment, (QueryTriggerInteraction)0);
				if (num)
				{
					blocker = (((Object)(object)((RaycastHit)(ref val10)).collider == (Object)null) ? "unknown" : $"{((Object)((RaycastHit)(ref val10)).collider).name}, layer={((Component)((RaycastHit)(ref val10)).collider).gameObject.layer}");
				}
				return !num;
			}
		}
	}
	internal sealed class CleanupWork
	{
		private readonly List<(string Name, Action Action)> steps = new List<(string, Action)>();

		internal int Remaining => steps.Count;

		internal void Add(string name, Action action)
		{
			steps.Add((name, action));
		}

		internal bool Run()
		{
			int num = 0;
			while (num < steps.Count)
			{
				(string, Action) tuple = steps[num];
				try
				{
					tuple.Item2();
					steps.RemoveAt(num);
				}
				catch (Exception error)
				{
					ModFaults.Report(tuple.Item1, error);
					num++;
				}
			}
			return steps.Count == 0;
		}
	}
	internal static class CleanupRetries
	{
		private sealed class Pending
		{
			internal CleanupWork Work;

			internal int Left = 3;

			internal long Due;
		}

		private static readonly List<Pending> pending = new List<Pending>();

		internal static bool HasPending => pending.Count != 0;

		internal static string Status
		{
			get
			{
				if (pending.Count != 0)
				{
					return "Some cleanup could not finish. See the log for the affected controls or resources. Restart the game before unloading the patch.";
				}
				return "";
			}
		}

		internal static bool CanCreate => pending.Count < 256;

		internal static void Submit(CleanupWork work)
		{
			if (!work.Run())
			{
				Retry(work);
			}
		}

		internal static void Retry(CleanupWork work)
		{
			pending.Add(new Pending
			{
				Work = work,
				Due = Stopwatch.GetTimestamp() + Stopwatch.Frequency
			});
		}

		internal static void RetireCompleted(CleanupWork work)
		{
			if (work.Remaining != 0)
			{
				return;
			}
			for (int num = pending.Count - 1; num >= 0; num--)
			{
				if (pending[num].Work == work)
				{
					pending.RemoveAt(num);
				}
			}
		}

		internal static void Tick()
		{
			if (CleanupRetries.pending.Count == 0)
			{
				return;
			}
			long timestamp = Stopwatch.GetTimestamp();
			for (int num = CleanupRetries.pending.Count - 1; num >= 0; num--)
			{
				Pending pending = CleanupRetries.pending[num];
				if (pending.Left != 0 && timestamp >= pending.Due)
				{
					pending.Left--;
					pending.Due = timestamp + Stopwatch.Frequency;
					if (pending.Work.Run())
					{
						CleanupRetries.pending.RemoveAt(num);
					}
					else if (pending.Left == 0)
					{
						ModFaults.Report("Cleanup retry exhaustion", new InvalidOperationException("Cleanup stopped after three retries; unresolved native state retained. Restart is required before creating more affected controls."));
					}
				}
			}
		}
	}
	internal static class DistantCharacterDetails
	{
		private sealed class State
		{
			internal Character Character;

			internal GameObject Object;

			internal Transform Transform;

			internal CharacterCommunication? Communication;

			internal Salsa? Salsa;

			internal IKSolverLookAt? Look;

			internal bool Far;
		}

		private static readonly Dictionary<nint, State> characters = new Dictionary<IntPtr, State>();

		private static readonly Dictionary<nint, State> lips = new Dictionary<IntPtr, State>();

		private static readonly Dictionary<nint, State> looks = new Dictionary<IntPtr, State>();

		private static readonly List<nint> retired = new List<IntPtr>();

		private static readonly Harmony harmony = new Harmony("hvizeu.nivalis.unofficialpatch.distant-details");

		private static bool hooks;

		private static bool running;

		private static bool failed;

		private static float nextCheck;

		internal static bool HooksPending => hooks;

		internal static int Count => characters.Count;

		internal static void Start()
		{
			if (failed || hooks || !PerformanceCompatibility.Owns(PerformanceFeature.DistantCharacterDetails))
			{
				return;
			}
			hooks = true;
			try
			{
				Patch(typeof(Salsa), "LateUpdate", "LipPrefix");
				Patch(typeof(IKSolverLookAt), "SolveHead", "LookPrefix");
				Patch(typeof(IKSolverLookAt), "SolveEyes", "LookPrefix");
				Patch(typeof(Character), "OnPoolingDisable", "RetirePrefix");
				Patch(typeof(CharacterCommunication), "StartDialogue", "DialoguePrefix");
				Patch(typeof(CharacterCommunication), "StartTalk", "DialoguePrefix");
				running = true;
				nextCheck = 0f;
				PerformanceCompatibility.Health(PerformanceFeature.DistantCharacterDetails, null);
			}
			catch
			{
				failed = true;
				PerformanceCompatibility.Health(PerformanceFeature.DistantCharacterDetails, "Presentation hooks failed; disabled for this session");
				Stop();
				throw;
			}
		}

		private static void Patch(Type type, string target, string prefix)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			harmony.Patch((MethodBase)(AccessTools.Method(type, target, (Type[])null, (Type[])null) ?? throw new MissingMethodException(type.FullName, target)), new HarmonyMethod(typeof(DistantCharacterDetails), prefix, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		internal static void Inspect(Character character)
		{
			if (running && !((Object)(object)character == (Object)null) && !characters.ContainsKey(((Il2CppObjectBase)character).Pointer))
			{
				if (characters.Count >= 1024)
				{
					throw new InvalidOperationException("Distant character presentation inventory exceeded its limit.");
				}
				CharacterCommunication communication = character.Communication;
				CharacterIK iK = character.IK;
				LookAtIK val = (((Object)(object)iK == (Object)null) ? null : iK.lookIK);
				State state = new State
				{
					Character = character,
					Object = ((Component)character).gameObject,
					Transform = ((BaseCharacter)character).ThisTransform,
					Communication = communication,
					Salsa = (((Object)(object)communication == (Object)null) ? null : communication.Salsa),
					Look = (((Object)(object)val == (Object)null) ? null : val.solver)
				};
				if (((Object)(object)state.Salsa != (Object)null && lips.ContainsKey(((Il2CppObjectBase)state.Salsa).Pointer)) || (state.Look != null && looks.ContainsKey(((Il2CppObjectBase)state.Look).Pointer)))
				{
					throw new InvalidOperationException("Characters share a presentation component; distance ownership is ambiguous.");
				}
				characters.Add(((Il2CppObjectBase)character).Pointer, state);
				if ((Object)(object)state.Salsa != (Object)null)
				{
					lips[((Il2CppObjectBase)state.Salsa).Pointer] = state;
				}
				if (state.Look != null)
				{
					looks[((Il2CppObjectBase)state.Look).Pointer] = state;
				}
			}
		}

		internal static bool WantsTick(float now)
		{
			if (running && characters.Count > 0)
			{
				return now >= nextCheck;
			}
			return false;
		}

		internal static void Tick()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			if (WantsTick(unscaledTime))
			{
				Camera main = Camera.main;
				Tick(unscaledTime, ((Object)(object)main != (Object)null) ? new Vector3?(((Component)main).transform.position) : ((Vector3?)null));
			}
		}

		internal static void Tick(float now, Vector3? cameraPosition)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			if (!WantsTick(now))
			{
				return;
			}
			nextCheck = now + 0.25f;
			try
			{
				bool hasValue = cameraPosition.HasValue;
				Vector3 valueOrDefault = cameraPosition.GetValueOrDefault();
				retired.Clear();
				foreach (KeyValuePair<IntPtr, State> character in characters)
				{
					State value = character.Value;
					if ((Object)(object)value.Character == (Object)null || (Object)(object)value.Transform == (Object)null || (Object)(object)value.Object == (Object)null || !value.Object.activeInHierarchy)
					{
						retired.Add(character.Key);
						continue;
					}
					bool flag = (Object)(object)value.Communication != (Object)null && value.Communication.IsPlayerDialogue;
					bool far = false;
					if (hasValue && !flag)
					{
						Vector3 position = value.Transform.position;
						far = DistantPresentationPolicy.Far(DistantPresentationPolicy.SquaredDistance(position.x, position.y, position.z, valueOrDefault.x, valueOrDefault.y, valueOrDefault.z), value.Far, 25f, 22f);
					}
					value.Far = far;
				}
				foreach (IntPtr item in retired)
				{
					Retire(item);
				}
				retired.Clear();
			}
			catch (Exception ex)
			{
				failed = true;
				Plugin.ModLog.LogError((object)("Distant character presentation stopped for this session. " + ex));
				PerformanceCompatibility.Health(PerformanceFeature.DistantCharacterDetails, "Presentation check failed; disabled for this session");
				RenderingOptimizations.Stop();
			}
		}

		internal static bool LipPrefix(Salsa __instance)
		{
			if (running && lips.TryGetValue(((Il2CppObjectBase)__instance).Pointer, out State value))
			{
				return !value.Far;
			}
			return true;
		}

		internal static bool LookPrefix(IKSolverLookAt __instance)
		{
			if (running && looks.TryGetValue(((Il2CppObjectBase)__instance).Pointer, out State value))
			{
				return !value.Far;
			}
			return true;
		}

		private static void RetirePrefix(Character __instance)
		{
			Retire(((Il2CppObjectBase)__instance).Pointer);
		}

		private static void DialoguePrefix(CharacterCommunication __instance)
		{
			foreach (State value in characters.Values)
			{
				CharacterCommunication? communication = value.Communication;
				if (((communication != null) ? new IntPtr?(((Il2CppObjectBase)communication).Pointer) : ((IntPtr?)null)) == ((Il2CppObjectBase)__instance).Pointer)
				{
					value.Far = false;
					break;
				}
			}
		}

		internal static void Retire(nint id)
		{
			if (characters.Remove(id, out State value))
			{
				if (value.Salsa != null)
				{
					lips.Remove(((Il2CppObjectBase)value.Salsa).Pointer);
				}
				if (value.Look != null)
				{
					looks.Remove(((Il2CppObjectBase)value.Look).Pointer);
				}
			}
		}

		internal static bool Stop()
		{
			if (!failed && (running || hooks))
			{
				PerformanceCompatibility.Health(PerformanceFeature.DistantCharacterDetails, "Stopped; waiting for rendering owner");
			}
			running = false;
			characters.Clear();
			lips.Clear();
			looks.Clear();
			retired.Clear();
			if (!hooks)
			{
				return true;
			}
			if (!RenderingOptimizations.TryRestore("distant presentation hooks", (Action)harmony.UnpatchSelf))
			{
				return false;
			}
			hooks = false;
			return true;
		}
	}
	internal static class DistantCharacterMeshes
	{
		private sealed class State
		{
			internal LODGroup Group;

			internal LOD[] Original;

			internal bool ChangedLods;

			internal readonly List<(Renderer Renderer, bool Original)> Retired = new List<(Renderer, bool)>();
		}

		private static readonly Dictionary<int, State> states = new Dictionary<int, State>();

		private static readonly List<int> retired = new List<int>();

		internal static int Count => states.Count;

		internal static bool OwnsLod(int id)
		{
			if (states.TryGetValue(id, out State value))
			{
				return value.ChangedLods;
			}
			return false;
		}

		internal static bool SmallGlasses(string character, string renderer, int triangles, int bones, int slots)
		{
			if (bones != 1)
			{
				return false;
			}
			switch (BalancedDetailPolicy.ObjectName(character))
			{
			case "Ceres Coilson":
				if (!(renderer == "Glasses_LOD_04") || triangles != 96 || slots != 2)
				{
					break;
				}
				return true;
			case "Steven McFellow":
				if (!(renderer == "Glasses_LOD_04") || triangles != 30 || slots != 2)
				{
					break;
				}
				return true;
			case "Mizzy Weiss":
				if (!(renderer == "Glasses_LOD_04") || triangles != 32 || slots != 1)
				{
					break;
				}
				return true;
			case "Roxi Fynx":
				if (!(renderer == "Glasses_LOD_04") || triangles != 32 || slots != 1)
				{
					break;
				}
				return true;
			case "Alexandria":
				if (!(renderer == "Glasses_LOD_04") || triangles != 48 || slots != 2)
				{
					break;
				}
				return true;
			case "Rice Walket":
				if (!(renderer == "Sunglasses_LOD_04") || triangles != 7 || slots != 1)
				{
					break;
				}
				return true;
			case "Male007":
				if (!(renderer == "GLASSES_LOD_004") || triangles != 90 || slots != 1)
				{
					break;
				}
				return true;
			case "Lynnphora Adams":
				if (!(renderer == "Glasses_LOD_04") || triangles != 20 || slots != 1)
				{
					break;
				}
				return true;
			case "Male008":
				if (!(renderer == "Garret_Glasses1_LOD_04") || triangles != 28 || slots != 1)
				{
					break;
				}
				return true;
			case "Milo":
				if (!(renderer == "Glasses_LOD_04") || triangles != 32 || slots != 1)
				{
					break;
				}
				return true;
			case "Random Male 03":
				if (!(renderer == "Glasses _LOD_004") || triangles != 27 || slots != 1)
				{
					break;
				}
				return true;
			case "Random Male 03_2":
				if (!(renderer == "Glasses _LOD_004") || triangles != 27 || slots != 1)
				{
					break;
				}
				return true;
			case "Dagmar Fitz":
				if (!(renderer == "Glasses_LOD_004") || triangles != 31 || slots != 2)
				{
					break;
				}
				return true;
			case "Mila Kalcifer":
				if (!(renderer == "Glasses_LOD_04") || triangles != 5 || slots != 1)
				{
					break;
				}
				return true;
			}
			return false;
		}

		internal static void Inspect(LODGroup group)
		{
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Expected O, but got Unknown
			if (!RenderingOptions.DistantCharacterMeshesEnabled || (Object)(object)group == (Object)null || states.ContainsKey(((Object)group).GetInstanceID()))
			{
				return;
			}
			Character component = ((Component)group).GetComponent<Character>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.LODGroup != (Object)(object)group)
			{
				return;
			}
			string name = BalancedDetailPolicy.ObjectName(((Object)((Component)component).gameObject).name);
			bool flag;
			switch (name)
			{
			case "Ceres Coilson":
			case "Mila Kalcifer":
			case "Lynnphora Adams":
			case "Steven McFellow":
			case "Dagmar Fitz":
			case "Mizzy Weiss":
			case "Rice Walket":
			case "Male007":
			case "Male008":
			case "Roxi Fynx":
			case "Alexandria":
			case "Milo":
			case "Random Male 03":
			case "Random Male 03_2":
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			if (!flag)
			{
				return;
			}
			LOD[] array = ((IEnumerable<LOD>)group.GetLODs()).ToArray();
			if (array.Length != 5 || array[0].screenRelativeTransitionHeight != 0.5f || array[4].screenRelativeTransitionHeight != 0.02f)
			{
				return;
			}
			State state = new State
			{
				Group = group,
				Original = array
			};
			Renderer[] array2 = ((IEnumerable<Renderer>)array[4].renderers).Where((Renderer r) => !Omit(name, r)).ToArray();
			state.ChangedLods = array2.Length != ((Il2CppArrayBase<Renderer>)(object)array[4].renderers).Length && array2.Length != 0;
			if (!state.ChangedLods)
			{
				return;
			}
			if (states.Count >= 1024)
			{
				throw new InvalidOperationException("Distant character mesh inventory exceeded its limit.");
			}
			states.Add(((Object)group).GetInstanceID(), state);
			if (!state.ChangedLods)
			{
				return;
			}
			LOD[] array3 = ((IEnumerable<LOD>)array).Select((Func<LOD, LOD>)((LOD l) => new LOD(l.screenRelativeTransitionHeight, l.renderers)
			{
				fadeTransitionWidth = l.fadeTransitionWidth
			})).ToArray();
			array3[4] = new LOD(array[4].screenRelativeTransitionHeight, Il2CppReferenceArray<Renderer>.op_Implicit(array2))
			{
				fadeTransitionWidth = array[4].fadeTransitionWidth
			};
			HashSet<IntPtr> hashSet = (from r in array3.SelectMany((LOD l) => (IEnumerable<Renderer>)l.renderers)
				where (Object)(object)r != (Object)null
				select ((Il2CppObjectBase)r).Pointer).ToHashSet();
			foreach (Renderer item in (Il2CppArrayBase<Renderer>)(object)array[4].renderers)
			{
				if ((Object)(object)item != (Object)null && !hashSet.Contains(((Il2CppObjectBase)item).Pointer))
				{
					state.Retired.Add((item, item.forceRenderingOff));
				}
			}
			group.SetLODs(Il2CppReferenceArray<LOD>.op_Implicit(array3));
			foreach (var item2 in state.Retired)
			{
				item2.Renderer.forceRenderingOff = true;
			}
		}

		private static bool Omit(string character, Renderer renderer)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)renderer == (Object)null || (int)renderer.shadowCastingMode != 0)
			{
				return false;
			}
			SkinnedMeshRenderer val = ((Il2CppObjectBase)renderer).TryCast<SkinnedMeshRenderer>();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Mesh sharedMesh = val.sharedMesh;
			if ((Object)(object)sharedMesh == (Object)null || sharedMesh.subMeshCount > 2)
			{
				return false;
			}
			int num = 0;
			for (int i = 0; i < sharedMesh.subMeshCount; i++)
			{
				if ((int)sharedMesh.GetTopology(i) != 0)
				{
					return false;
				}
				num += checked((int)sharedMesh.GetIndexCount(i)) / 3;
			}
			return SmallGlasses(character, ((Object)((Component)renderer).gameObject).name, num, ((Il2CppArrayBase<Transform>)(object)val.bones).Length, ((Il2CppArrayBase<Material>)(object)renderer.sharedMaterials).Length);
		}

		internal static void Prune()
		{
			retired.Clear();
			foreach (KeyValuePair<int, State> state in states)
			{
				if ((Object)(object)state.Value.Group == (Object)null)
				{
					retired.Add(state.Key);
				}
			}
			foreach (int item in retired)
			{
				if (!Restore(states[item]))
				{
					throw new InvalidOperationException("A removed LODGroup still has unrestored distant mesh state.");
				}
				states.Remove(item);
			}
			retired.Clear();
		}

		internal static void Stop()
		{
			KeyValuePair<int, State>[] array = states.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<int, State> keyValuePair = array[i];
				if (Restore(keyValuePair.Value))
				{
					states.Remove(keyValuePair.Key);
				}
			}
		}

		private static bool Restore(State state)
		{
			bool flag;
			if (flag = !state.ChangedLods || RenderingOptimizations.TryRestore("distant character LOD", delegate
			{
				if ((Object)(object)state.Group != (Object)null)
				{
					state.Group.SetLODs(Il2CppReferenceArray<LOD>.op_Implicit(state.Original));
				}
			}))
			{
				foreach (var item in state.Retired)
				{
					flag &= RenderingOptimizations.TryRestore("distant accessory visibility", delegate
					{
						if ((Object)(object)item.Renderer != (Object)null)
						{
							item.Renderer.forceRenderingOff = item.Original;
						}
					});
				}
			}
			return flag;
		}
	}
	internal static class DistantWorldPanels
	{
		private sealed class State
		{
			internal MeshRenderer Renderer;

			internal bool Hidden;
		}

		private static readonly Dictionary<int, State> states = new Dictionary<int, State>();

		private static readonly List<int> retired = new List<int>();

		private static float nextCheck;

		internal static int Count => states.Count;

		internal static void Inspect(Transform node)
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			if (!RenderingOptions.DistantWorldPanelsEnabled)
			{
				return;
			}
			string text = BalancedDetailPolicy.ObjectName(((Object)((Component)node).gameObject).name);
			bool flag;
			switch (text)
			{
			case "Animated_Billboard_1x1":
			case "Animated_Billboard_1x2":
			case "Animated_Billboard_2x1":
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			if (!flag)
			{
				return;
			}
			MeshRenderer component = ((Component)node).GetComponent<MeshRenderer>();
			if ((Object)(object)component == (Object)null || states.ContainsKey(((Object)component).GetInstanceID()) || ((Renderer)component).forceRenderingOff || (int)((Renderer)component).shadowCastingMode != 0)
			{
				return;
			}
			MeshFilter component2 = ((Component)node).GetComponent<MeshFilter>();
			Mesh val = ((component2 != null) ? component2.sharedMesh : null);
			if ((Object)(object)val == (Object)null || val.subMeshCount != 1 || (int)val.GetTopology(0) != 0)
			{
				return;
			}
			Il2CppReferenceArray<Material> sharedMaterials = ((Renderer)component).sharedMaterials;
			if (((Il2CppArrayBase<Material>)(object)sharedMaterials).Length != 1 || (Object)(object)((Il2CppArrayBase<Material>)(object)sharedMaterials)[0] == (Object)null)
			{
				return;
			}
			Material val2 = ((Il2CppArrayBase<Material>)(object)sharedMaterials)[0];
			Shader shader = val2.shader;
			if ((Object)(object)shader == (Object)null)
			{
				return;
			}
			Bounds bounds = val.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			Vector3 lossyScale = node.lossyScale;
			if (DistantPresentationPolicy.SmallPanel(text, ((Object)val).name, val.GetIndexCount(0), ((Object)val2).name, ((Object)shader).name, Math.Abs(size.x * lossyScale.x), Math.Abs(size.y * lossyScale.y)))
			{
				if (states.Count >= 256)
				{
					throw new InvalidOperationException("Small world-panel inventory exceeded its limit.");
				}
				states.Add(((Object)component).GetInstanceID(), new State
				{
					Renderer = component
				});
			}
		}

		internal static bool WantsTick(float now)
		{
			if (states.Count > 0)
			{
				return now >= nextCheck;
			}
			return false;
		}

		internal static void Tick()
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			if (WantsTick(unscaledTime))
			{
				Camera main = Camera.main;
				Tick(unscaledTime, ((Object)(object)main != (Object)null) ? new Vector3?(((Component)main).transform.position) : ((Vector3?)null));
			}
		}

		internal static void Tick(float now, Vector3? cameraPosition)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			if (!WantsTick(now))
			{
				return;
			}
			nextCheck = now + 0.25f;
			bool hasValue = cameraPosition.HasValue;
			Vector3 valueOrDefault = cameraPosition.GetValueOrDefault();
			retired.Clear();
			foreach (KeyValuePair<int, State> state in states)
			{
				State value = state.Value;
				if ((Object)(object)value.Renderer == (Object)null)
				{
					retired.Add(state.Key);
					continue;
				}
				bool flag = false;
				if (hasValue && ((Component)value.Renderer).gameObject.activeInHierarchy)
				{
					Vector3 center = ((Renderer)value.Renderer).bounds.m_Center;
					flag = DistantPresentationPolicy.Far(DistantPresentationPolicy.SquaredDistance(center.x, center.y, center.z, valueOrDefault.x, valueOrDefault.y, valueOrDefault.z), value.Hidden, 40f, 35f);
				}
				if (flag != value.Hidden)
				{
					if (flag)
					{
						value.Hidden = true;
						((Renderer)value.Renderer).forceRenderingOff = true;
					}
					else
					{
						((Renderer)value.Renderer).forceRenderingOff = false;
						value.Hidden = false;
					}
				}
			}
			foreach (int item in retired)
			{
				states.Remove(item);
			}
			retired.Clear();
		}

		internal static void Stop()
		{
			KeyValuePair<int, State>[] array = states.ToArray();
			for (int i = 0; i < array.Length; i++)
			{
				KeyValuePair<int, State> keyValuePair = array[i];
				State state = keyValuePair.Value;
				if (!state.Hidden || RenderingOptimizations.TryRestore("small world panel", delegate
				{
					if ((Object)(object)state.Renderer != (Object)null)
					{
						((Renderer)state.Renderer).forceRenderingOff = false;
					}
				}))
				{
					states.Remove(keyValuePair.Key);
				}
			}
			nextCheck = 0f;
		}
	}
	internal static class LightingPatches
	{
		private sealed class LightingState
		{
			internal readonly LightingClockGate Clock = new LightingClockGate();

			internal readonly ExactCache Snapshot = new ExactCache();
		}

		[HarmonyPatch(typeof(LightCycleManager), "UpdateLightingInternal")]
		private static class Refresh
		{
			private static bool Prefix(LightCycleManager __instance, bool updateProbesIntensity, bool reuseUnchanged, out bool __state)
			{
				__state = false;
				if (!Plugin.Lighting || failed.Contains(((Il2CppObjectBase)__instance).Pointer))
				{
					return true;
				}
				bool flag;
				try
				{
					if (LightCycleManager.APPLY_FIXES)
					{
						Invalidate();
						return true;
					}
					LightingState lightingState = Cache(((Il2CppObjectBase)__instance).Pointer);
					if (!reuseUnchanged || __instance.inTransition || !updateProbesIntensity)
					{
						lightingState.Snapshot.Invalidate();
						lightingState.Clock.Reset();
						lastOwner = 0;
						return true;
					}
					if (!lightingState.Clock.Stable(__instance.currentTime, __instance.currentTimeRemapped))
					{
						lightingState.Snapshot.Invalidate();
						lastOwner = 0;
						return true;
					}
					Span<byte> buffer = stackalloc byte[1024];
					SnapshotWriter key = new SnapshotWriter(buffer);
					Capture(__instance, ref key);
					flag = lastOwner == ((Il2CppObjectBase)__instance).Pointer && lightingState.Snapshot.Matches(key.Written);
				}
				catch (Exception error)
				{
					Failed(__instance, error);
					return true;
				}
				if (flag)
				{
					__instance.sunLightComponent.UpdateLight(false);
					TimeOfDayController otherTimeOfDayController = __instance.otherTimeOfDayController;
					if ((Object)(object)otherTimeOfDayController != (Object)null)
					{
						otherTimeOfDayController.m_SkyTime = Math.Abs(__instance.currentTimeRemapped);
						otherTimeOfDayController.UpdateSkyForCurrentTime();
					}
					Skipped++;
					if (Skipped == 1)
					{
						Plugin.ModLog.LogInfo((object)"First unchanged lighting refresh reused; sun transforms and secondary sky callbacks continue.");
					}
					return false;
				}
				__state = true;
				return true;
			}

			private static void Postfix(LightCycleManager __instance, bool __state, bool __runOriginal)
			{
				if (!__state || failed.Contains(((Il2CppObjectBase)__instance).Pointer))
				{
					return;
				}
				if (!__runOriginal)
				{
					Cache(((Il2CppObjectBase)__instance).Pointer).Snapshot.Invalidate();
					lastOwner = 0;
					return;
				}
				try
				{
					Span<byte> buffer = stackalloc byte[1024];
					SnapshotWriter key = new SnapshotWriter(buffer);
					Capture(__instance, ref key);
					Cache(((Il2CppObjectBase)__instance).Pointer).Snapshot.Store(key.Written);
					lastOwner = ((Il2CppObjectBase)__instance).Pointer;
				}
				catch (Exception error)
				{
					Failed(__instance, error);
				}
			}

			private static void Finalizer(LightCycleManager __instance, Exception? __exception)
			{
				if (__exception != null)
				{
					if (caches.TryGetValue(((Il2CppObjectBase)__instance).Pointer, out LightingState value))
					{
						value.Snapshot.Invalidate();
						value.Clock.Reset();
					}
					lastOwner = 0;
				}
			}
		}

		[HarmonyPatch(typeof(LightCycleManager), "OnDestroy")]
		private static class Destroy
		{
			private static void Prefix(LightCycleManager __instance)
			{
				caches.Remove(((Il2CppObjectBase)__instance).Pointer);
				failed.Remove(((Il2CppObjectBase)__instance).Pointer);
				if (lastOwner == ((Il2CppObjectBase)__instance).Pointer)
				{
					lastOwner = 0;
				}
			}
		}

		private static nint lastOwner;

		private static readonly Dictionary<nint, LightingState> caches = new Dictionary<IntPtr, LightingState>();

		private static readonly HashSet<nint> failed = new HashSet<IntPtr>();

		internal static long Skipped;

		internal static void Invalidate()
		{
			caches.Clear();
			lastOwner = 0;
		}

		internal static void Clear()
		{
			caches.Clear();
			failed.Clear();
			lastOwner = 0;
		}

		private static LightingState Cache(nint owner)
		{
			if (!caches.TryGetValue(owner, out LightingState value))
			{
				caches.Add(owner, value = new LightingState());
			}
			return value;
		}

		private static void Capture(LightCycleManager owner, ref SnapshotWriter key)
		{
			key.Fields(((Il2CppObjectBase)owner).Pointer, 24, 112);
			key.Fields(((Il2CppObjectBase)owner).Pointer, 136, 32);
			key.Value(owner.LightObjects?._version ?? (-1));
			SceneFogSettings sceneOverrides = owner.sceneOverrides;
			key.Fields((sceneOverrides != null) ? ((Il2CppObjectBase)sceneOverrides).Pointer : IntPtr.Zero, 24, 129);
			LightCycleSettings currentLightCycleSettings = owner.currentLightCycleSettings;
			key.Fields((currentLightCycleSettings != null) ? ((Il2CppObjectBase)currentLightCycleSettings).Pointer : IntPtr.Zero, 24, 168);
			IntPtr? obj;
			if (currentLightCycleSettings == null)
			{
				obj = null;
			}
			else
			{
				VolumetricSettings volumetricSettings = currentLightCycleSettings.volumetricSettings;
				obj = ((volumetricSettings != null) ? new IntPtr?(((Il2CppObjectBase)volumetricSettings).Pointer) : ((IntPtr?)null));
			}
			key.Fields(obj ?? IntPtr.Zero, 16, 36);
			IntPtr? obj2;
			if (currentLightCycleSettings == null)
			{
				obj2 = null;
			}
			else
			{
				GlobalFogSettings fogSettings = currentLightCycleSettings.fogSettings;
				obj2 = ((fogSettings != null) ? new IntPtr?(((Il2CppObjectBase)fogSettings).Pointer) : ((IntPtr?)null));
			}
			key.Fields(obj2 ?? IntPtr.Zero, 16, 40);
			IntPtr? obj3;
			if (currentLightCycleSettings == null)
			{
				obj3 = null;
			}
			else
			{
				GlobalFogSettings rainSettings = currentLightCycleSettings.rainSettings;
				obj3 = ((rainSettings != null) ? new IntPtr?(((Il2CppObjectBase)rainSettings).Pointer) : ((IntPtr?)null));
			}
			key.Fields(obj3 ?? IntPtr.Zero, 16, 40);
			WeatherManager weatherManager = owner.weatherManager;
			key.Fields((weatherManager != null) ? ((Il2CppObjectBase)weatherManager).Pointer : IntPtr.Zero, 48, 32);
		}

		private static void Failed(LightCycleManager owner, Exception error)
		{
			Cache(((Il2CppObjectBase)owner).Pointer).Snapshot.Invalidate();
			lastOwner = 0;
			failed.Add(((Il2CppObjectBase)owner).Pointer);
			ModFaults.Report("Lighting cache disabled for this scene; native refreshes continue", error);
		}
	}
	[HarmonyPatch(typeof(ResolveComplaintSubAction), "Enter")]
	internal static class ManagerComplaintPatch
	{
		internal readonly record struct Scope(ManageComplaintTask? Task, AgentGhost? Customer, State? Visit);

		internal static void Prefix(State state, out Scope __state)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			__state = default(Scope);
			try
			{
				ManageComplaintTask task = state.Task;
				if (task != null && !((StaffTask)task).IsCompleted)
				{
					CustomerGhost customer = task.Customer;
					AgentGhost val = ((customer != null) ? ((Il2CppObjectBase)customer).TryCast<AgentGhost>() : null);
					State val2 = ((val != null) ? val.VisitVenueState : null);
					if (val2 != null && (int)val2.ComplaintReason != 0 && (int)val2.Interaction == 0)
					{
						__state = new Scope(task, val, val2);
					}
				}
			}
			catch (Exception error)
			{
				ModFaults.Report("Manager complaint capture", error);
			}
		}

		internal static void Postfix(State state, Scope __state, bool __runOriginal)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Invalid comparison between Unknown and I4
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Invalid comparison between Unknown and I4
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Invalid comparison between Unknown and I4
			try
			{
				if (__runOriginal && __state.Task != null && __state.Visit != null && __state.Customer != null && state.Task != null && !(((Il2CppObjectBase)state.Task).Pointer != ((Il2CppObjectBase)__state.Task).Pointer) && ((StaffTask)__state.Task).IsCompleted && (int)((ActionState)state).Result == 1)
				{
					State visitVenueState = __state.Customer.VisitVenueState;
					bool flag = visitVenueState == null || ((Il2CppObjectBase)visitVenueState).Pointer != ((Il2CppObjectBase)__state.Visit).Pointer || (int)visitVenueState.ComplaintReason == 0 || (int)visitVenueState.Interaction > 0;
					if (!flag)
					{
						CustomerReaction interactionOutcome = visitVenueState.InteractionOutcome;
						bool flag2 = interactionOutcome - 1 <= 1;
						flag = !flag2;
					}
					if (!flag)
					{
						visitVenueState.Interaction = (CustomerInteraction)3;
					}
				}
			}
			catch (Exception error)
			{
				ModFaults.Report("Manager complaint review", error);
			}
		}
	}
	internal static class ManagerMenu
	{
		private sealed class View : IDisposable
		{
			internal readonly VenueStaffOverviewTab Owner;

			internal readonly int Id;

			private Action<UISubPanel>? visibility;

			private bool disposed;

			private readonly Button entry;

			private readonly RectTransform schedule;

			private readonly Vector2 originalScheduleTop;

			private CanvasBehaviourManager? entryCanvas;

			private bool lastPurchasing = true;

			private Button? returnFocus;

			private CanvasBehaviourManager? panelCanvas;

			private CanvasGroup? staffSurface;

			private float staffAlpha;

			private bool staffInteractable;

			private bool staffRaycasts;

			private readonly List<Func<bool>> validateMoney = new List<Func<bool>>();

			private GameObject? root;

			private Venue? venue;

			private ManagerPolicy draft = new ManagerPolicy();

			private SharedBudgetPolicy sharedDraft = new SharedBudgetPolicy();

			private long lastRevision = -1L;

			private string? lastCompatibility;

			private TextMeshProUGUI status;

			private ScrollRect scroll;

			private RectTransform content;

			private readonly List<Selectable> controls = new List<Selectable>();

			private readonly List<Action> refresh = new List<Action>();

			private readonly List<(Selectable Control, bool Enabled)> disabled = new List<(Selectable, bool)>();

			private GameObject? details;

			private bool dirty;

			private string applied = "";

			private int moneyStep = 50;

			internal View(VenueStaffOverviewTab owner)
			{
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0101: 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)
				//IL_015f: Unknown result type (might be due to invalid IL or missing references)
				//IL_016a: Unknown result type (might be due to invalid IL or missing references)
				//IL_017f: Unknown result type (might be due to invalid IL or missing references)
				//IL_018a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0195: Unknown result type (might be due to invalid IL or missing references)
				//IL_019a: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
				//IL_01be: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_0233: Unknown result type (might be due to invalid IL or missing references)
				Owner = owner;
				Id = ((Object)owner).GetInstanceID();
				Transform val = ((Component)owner).transform.Find("StaffTabWrapper");
				if ((Object)(object)val == (Object)null)
				{
					throw new InvalidOperationException("StaffTabWrapper was not found.");
				}
				Transform obj = val.Find("ScheduleAndStaffPanelWrapper");
				schedule = ((obj != null) ? ((Component)obj).GetComponent<RectTransform>() : null) ?? throw new InvalidOperationException("Staff schedule wrapper was not found.");
				Transform obj2 = val.Find("P_Element_TitleFrame");
				RectTransform val2 = ((obj2 != null) ? ((Component)obj2).GetComponent<RectTransform>() : null) ?? throw new InvalidOperationException("Staff title was not found.");
				originalScheduleTop = schedule.offsetMax;
				try
				{
					entry = Button(owner.hireButton, val, "ADVANCED MANAGER", delegate
					{
						Open(entry);
					});
					((Object)((Component)entry).gameObject).name = "Hvizeu.EditManagerBehavior";
					RectTransform component = ((Component)entry).GetComponent<RectTransform>();
					((Transform)component).localScale = Vector3.one;
					component.anchorMin = new Vector2(0f, 1f);
					component.anchorMax = Vector2.one;
					component.pivot = new Vector2(0.5f, 1f);
					float y = val2.anchoredPosition.y;
					Rect rect = val2.rect;
					float num = y - ((Rect)(ref rect)).height * val2.pivot.y - 12f;
					component.offsetMin = new Vector2(schedule.offsetMin.x, num - 48f);
					component.offsetMax = new Vector2(originalScheduleTop.x, num);
					LayoutElement component2 = ((Component)entry).GetComponent<LayoutElement>();
					if ((Object)(object)component2 != (Object)null)
					{
						component2.ignoreLayout = true;
					}
					schedule.offsetMax = new Vector2(originalScheduleTop.x, Math.Min(originalScheduleTop.y, num - 64f));
					Navigation navigation = ((Selectable)entry).navigation;
					navigation.mode = (Mode)3;
					((Selectable)entry).navigation = navigation;
					ManualUINavigation component3 = ((Component)entry).GetComponent<ManualUINavigation>();
					if ((Object)(object)component3 != (Object)null)
					{
						component3._autoNavigation = navigation;
						bool searchSelectableOnUp = (component3.searchSelectableOnDown = true);
						component3.searchSelectableOnUp = searchSelectableOnUp;
						searchSelectableOnUp = (component3.searchSelectableOnRight = true);
						component3.searchSelectableOnLeft = searchSelectableOnUp;
					}
					CanvasBehaviourManager.RegisterRuntimeChildren(((Component)entry).gameObject, ref entryCanvas);
					visibility = Action<UISubPanel>.op_Implicit((Action<UISubPanel>)delegate
					{
						try
						{
							Refreshed();
						}
						catch (Exception error)
						{
							ModFaults.Report("Manager menu visibility", error);
						}
					});
					((UISubPanel)Owner).OnVisibilityChanged += visibility;
					Refreshed();
					Plugin.ModLog.LogInfo((object)"Added Edit Manager Behavior below the Staff and Working Schedule heading.");
				}
				catch
				{
					Dispose();
					throw;
				}
			}

			internal void Refreshed()
			{
				if (disposed)
				{
					return;
				}
				bool isVisible = ((UISubPanel)Owner).IsVisible;
				SetVisible(this, isVisible);
				if (!isVisible)
				{
					Close();
					return;
				}
				Venue forVenue = Owner._forVenue;
				bool flag = (Object)(object)forVenue != (Object)null && ((BaseProperty)forVenue).PlayerOwned;
				if (((Component)entry).gameObject.activeSelf != flag)
				{
					((Component)entry).gameObject.SetActive(flag);
				}
				RefreshEntry();
			}

			private void RefreshEntry()
			{
				if (!((Object)(object)entry == (Object)null))
				{
					bool flag = ManagerPurchasingCompatibility.Enabled && (Object)(object)root == (Object)null;
					if (((Selectable)entry).interactable != flag)
					{
						((Selectable)entry).interactable = flag;
					}
					string reason = ManagerPurchasingCompatibility.Reason;
					if (lastPurchasing != Plugin.Purchasing || lastCompatibility != reason)
					{
						lastPurchasing = Plugin.Purchasing;
						lastCompatibility = reason;
						RelabelButton(((Component)entry).gameObject, (reason != null) ? "FARM FIRST OWNS MANAGER PURCHASING" : (Plugin.Purchasing ? "ADVANCED MANAGER" : "MANAGER PURCHASING DISABLED"));
					}
				}
			}

			internal void Tick()
			{
				if (!((UISubPanel)Owner).IsVisible)
				{
					SetVisible(this, active: false);
					Close();
					return;
				}
				if (lastPurchasing != Plugin.Purchasing || lastCompatibility != ManagerPurchasingCompatibility.Reason)
				{
					RefreshEntry();
				}
				if ((Object)(object)root == (Object)null)
				{
					return;
				}
				Venue forVenue = Owner._forVenue;
				if (!((Object)(object)forVenue == (Object)null))
				{
					string guid = ((BaseProperty)forVenue).Guid;
					Venue? obj = venue;
					if (!(guid != ((obj != null) ? ((BaseProperty)obj).Guid : null)) && ManagerPurchasingCompatibility.Enabled)
					{
						ManagerPolicies.AdvanceDay();
						if (lastRevision != ManagerPolicies.Revision)
						{
							lastRevision = ManagerPolicies.Revision;
							Changed(edit: false);
						}
						if ((Object)(object)EventSystem.current != (Object)null)
						{
							GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject;
							if ((Object)(object)currentSelectedGameObject == (Object)null || !currentSelectedGameObject.transform.IsChildOf(root.transform))
							{
								controls[0].Select();
							}
						}
						return;
					}
				}
				Close();
			}

			private void Open(Button source)
			{
				//IL_009e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a4: Expected O, but got Unknown
				Close();
				returnFocus = source;
				venue = Owner._forVenue;
				if ((Object)(object)venue == (Object)null || !((BaseProperty)venue).PlayerOwned || !ManagerPurchasingCompatibility.Enabled)
				{
					return;
				}
				ManagerPolicies.AdvanceDay();
				draft = ManagerPolicies.Get(venue);
				sharedDraft = ManagerPolicies.Shared;
				lastRevision = ManagerPolicies.Revision;
				dirty = false;
				applied = "Changes apply to the next restock. Save your game to keep them.";
				try
				{
					Build();
					RefreshEntry();
				}
				catch (Exception ex)
				{
					Close();
					ManualLogSource modLog = Plugin.ModLog;
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(38, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Unable to open manager configuration: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					modLog.LogError(val);
				}
			}

			private void Build()
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0108: Unknown result type (might be due to invalid IL or missing references)
				//IL_010d: Unknown result type (might be due to invalid IL or missing references)
				//IL_010e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0190: Unknown result type (might be due to invalid IL or missing references)
				//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0338: Unknown result type (might be due to invalid IL or missing references)
				//IL_034e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0364: Unknown result type (might be due to invalid IL or missing references)
				//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
				//IL_0400: Unknown result type (might be due to invalid IL or missing references)
				//IL_041a: Unknown result type (might be due to invalid IL or missing references)
				//IL_042a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0b28: Unknown result type (might be due to invalid IL or missing references)
				//IL_0b43: Unknown result type (might be due to invalid IL or missing references)
				//IL_0b58: Unknown result type (might be due to invalid IL or missing references)
				//IL_0b6c: Unknown result type (might be due to invalid IL or missing references)
				//IL_09db: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a01: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a0c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a11: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a12: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a19: Unknown result type (might be due to invalid IL or missing references)
				//IL_0c1e: Unknown result type (might be due to invalid IL or missing references)
				TextMeshProUGUI workingHoursText = Owner.workingHoursText;
				root = ((Component)MenuVisuals.Rect(((Component)Owner).transform.parent, "Hvizeu.ManagerPolicy")).gameObject;
				MenuVisuals.CopyRect(((Component)Owner).transform, root.transform);
				RectTransform component = ((Component)Owner).GetComponent<RectTransform>();
				RectTransform component2 = root.GetComponent<RectTransform>();
				Rect rect = component.rect;
				float width = ((Rect)(ref rect)).width;
				rect = component.rect;
				float num = Math.Max(0f, (width - Math.Min(1240f, ((Rect)(ref rect)).width * 0.94f)) * 0.5f);
				rect = component.rect;
				float height = ((Rect)(ref rect)).height;
				rect = component.rect;
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(num, Math.Max(0f, (height - Math.Min(760f, ((Rect)(ref rect)).height * 0.94f)) * 0.5f));
				component2.offsetMin += val;
				component2.offsetMax -= val;
				root.SetActive(false);
				root.layer = ((Component)Owner).gameObject.layer;
				CanvasGroup obj = root.AddComponent<CanvasGroup>();
				obj.alpha = 1f;
				bool flag = (obj.ignoreParentGroups = true);
				bool interactable = (obj.blocksRaycasts = flag);
				obj.interactable = interactable;
				((Graphic)root.AddComponent<Image>()).color = new Color(0.09f, 0.085f, 0.078f, 1f);
				root.transform.SetAsLastSibling();
				TextMeshProUGUI val2 = MenuVisuals.Text(root.transform, workingHoursText, ((BaseProperty)venue).GetName() + " / Manager", 24f);
				((Graphic)val2).color = new Color(0.84f, 0.68f, 0.43f);
				Place(((TMP_Text)val2).rectTransform, 20f, 4f, 20f, 38f, top: true);
				string[] array = (from row in (IEnumerable<VenueStaffListItem>)((Component)Owner).GetComponentsInChildren<VenueStaffListItem>(true)
					where (Object)(object)row._person != (Object)null && (Object)(object)row.toggleManage != (Object)null && row.toggleManage.isOn
					select row._person.DisplayedName).Distinct().ToArray();
				string text = ((array.Length == 0) ? "No manager assigned" : ("Managers: " + string.Join(", ", array.Take(3)) + ((array.Length > 3) ? $" +{array.Length - 3}" : "")));
				Place(((TMP_Text)MenuVisuals.Text(root.transform, workingHoursText, text + "\nApplies to all managers at this venue", 16f)).rectTransform, 20f, 42f, 20f, 40f, top: true);
				RectTransform val3 = MenuVisuals.Rect(root.transform, "PolicyViewport");
				val3.offsetMin = new Vector2(20f, 96f);
				val3.offsetMax = new Vector2(-46f, -88f);
				((Graphic)((Component)val3).gameObject.AddComponent<Image>()).color = Color.clear;
				((Component)val3).gameObject.AddComponent<RectMask2D>();
				scroll = ((Component)val3).gameObject.AddComponent<ScrollRect>();
				scroll.horizontal = false;
				scroll.vertical = true;
				scroll.movementType = (MovementType)2;
				scroll.scrollSensitivity = 36f;
				scroll.viewport = val3;
				content = MenuVisuals.Rect((Transform)(object)val3, "PolicyRows");
				content.anchorMin = new Vector2(0f, 1f);
				content.anchorMax = Vector2.one;
				content.pivot = new Vector2(0.5f, 1f);
				content.sizeDelta = Vector2.zero;
				scroll.content = content;
				VerticalLayoutGroup obj2 = ((Component)content).gameObject.AddComponent<VerticalLayoutGroup>();
				interactable = (((HorizontalOrVerticalLayoutGroup)obj2).childControlHeight = true);
				((HorizontalOrVerticalLayoutGroup)obj2).childControlWidth = interactable;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandHeight = false;
				((HorizontalOrVerticalLayoutGroup)obj2).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj2).spacing = 6f;
				((Component)content).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
				RectTransform parent = Section((Transform)(object)content, "Operating policy");
				Choice((Transform)(object)parent, "Priority", () => draft.Priority switch
				{
					OperatingPriority.SaveMoney => "Save money", 
					OperatingPriority.MenuAvailability => "Keep menu available", 
					_ => "Balanced", 
				}, delegate
				{
					draft.Preset((OperatingPriority)((int)(draft.Priority + 1) % 3));
				}, "Balanced spreads stock coverage. Save money favours cheaper complete batches. Keep menu available spreads batches across dishes.");
				RectTransform parent2 = Section((Transform)(object)content, "Purchasing");
				Choice((Transform)(object)parent2, "Restaurant funding priority", () => draft.Funding.ToString(), delegate
				{
					draft.Funding = (FundingPriority)((int)(draft.Funding + 1) % 3);
				}, "With shared budgets enabled, High / Normal / Low receive weighted shares of 4 / 2 / 1. Dish priorities apply within this restaurant.");
				Button expand = null;
				expand = Button(Owner.hireButton, (Transform)(object)parent2, "SHOW SETTINGS", delegate
				{
					details.SetActive(!details.activeSelf);
					RelabelButton(((Component)expand).gameObject, details.activeSelf ? "HIDE SETTINGS" : "SHOW SETTINGS");
					Reflow();
				});
				Height(((Component)expand).gameObject, 34f);
				controls.Add((Selectable)(object)expand);
				AutoScroll((Selectable)(object)expand);
				RectTransform val4 = MenuVisuals.Rect((Transform)(object)parent2, "PurchasingDetails");
				details = ((Component)val4).gameObject;
				VerticalLayoutGroup obj3 = details.AddComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj3).spacing = 6f;
				interactable = (((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = true);
				((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = interactable;
				((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false;
				Note((Transform)(object)val4, "Supply targets, daily venue budgets and shopping notifications use the game's saved management settings. Legacy stock formulas are retired.", 64f, 17f);
				Choice((Transform)(object)val4, "Supplier preference", () => draft.Suppliers.ToString(), delegate
				{
					draft.Suppliers = (SupplierPreference)((int)(draft.Suppliers + 1) % 3);
				}, "Nearby uses district connections, not a delivery-time guarantee. Every mode can use another supplier when stock runs out.");
				Money((Transform)(object)val4, "Cash reserve", () => draft.CashReserve, delegate(int value)
				{
					draft.CashReserve = value;
				}, "Purchases must leave this much in the venue owner's wallet. Emergency orders also respect this reserve.");
				Money((Transform)(object)val4, "Limit per restock", () => draft.SpendingLimit, delegate(int value)
				{
					draft.SpendingLimit = value;
				}, "Zero keeps the game's limit. Applies to the whole menu; never raises the game's allowance.");
				Choice((Transform)(object)val4, "Amount adjustment", () => $"{moneyStep} LIM", delegate
				{
					int num4 = moneyStep;
					moneyStep = num4 switch
					{
						1 => 10, 
						10 => 50, 
						50 => 100, 
						100 => 1000, 
						_ => 1, 
					};
				}, "Step used by the minus and plus buttons above.", edits: false);
				Choice((Transform)(object)val4, "Emergency purchases", () => (!draft.EmergencyPurchases) ? "Off" : "Allowed", delegate
				{
					draft.EmergencyPurchases = !draft.EmergencyPurchases;
				}, "For a dish without a covered batch, allow cheaper suppliers if the preferred order exceeds the budget.");
				details.SetActive(false);
				RectTransform parent3 = Section((Transform)(object)content, "All restaurants");
				Choice((Transform)(object)parent3, "Shared budgeting", () => (!sharedDraft.Enabled) ? "Off" : "On", delegate
				{
					sharedDraft.Enabled = !sharedDraft.Enabled;
				}, "One shared wallet reserve and daily manager ingredient limit. Other expenses are not charged to this limit. Save the game to keep settings and accounting.");
				Money((Transform)(object)parent3, "Shared cash reserve", () => sharedDraft.CashReserve, delegate(int value)
				{
					sharedDraft.CashReserve = value;
				}, "Every restaurant must respect the higher of this reserve and its own reserve. Other player expenses can still use this money.");
				Money((Transform)(object)parent3, "Daily ingredient limit", () => sharedDraft.DailyLimit, delegate(int value)
				{
					sharedDraft.DailyLimit = value;
				}, "Zero means unlimited. The gameplay day resets at 08:00. One complete batch may borrow another restaurant's share within all hard limits.");
				RectTransform val5 = MenuVisuals.Rect((Transform)(object)parent3, "TodaySpending");
				Height(((Component)val5).gameObject, 72f);
				TextMeshProUGUI spendText = MenuVisuals.Text((Transform)(object)val5, Owner.workingHoursText, "", 17f);
				refresh.Add(delegate
				{
					ManagerSpendLedger ledger = ManagerPolicies.Account.Ledger;
					((TMP_Text)spendText).text = $"Today: {(decimal)ledger.Total / 100m:0.00} LIM across restaurants · {(decimal)ledger.Spent.GetValueOrDefault(((BaseProperty)venue).Guid) / 100m:0.00} LIM here\n" + (ledger.Faulted ? "Paid purchasing suspended: transaction accounting needs recovery." : "Changing limits or restoring defaults does not erase spending.");
				});
				RectTransform parent4 = Section((Transform)(object)content, "Dish priorities");
				Note((Transform)(object)parent4, "Higher priorities receive complete batches first when ingredients or funds are limited.", 34f, 17f);
				List<IRecipe> list = ManagerPlanning.Menu(((Il2CppObjectBase)((BaseProperty)venue).Ghost).TryCast<VenueAreaGhost>() ?? throw new InvalidOperationException("Venue runtime state is unavailable."));
				if (list.Count == 0)
				{
					Note((Transform)(object)parent4, "No cookable menu items. Add a dish and its required equipment first.", 60f);
				}
				foreach (IRecipe item in list)
				{
					string id = ManagerPlanning.RecipeId(item);
					DishRow((Transform)(object)parent4, item.Output.type.Name, () => draft.DishPriority(id), delegate(int direction2)
					{
						draft.AdjustDishPriority(id, direction2);
					});
				}
				RectTransform parent5 = Section((Transform)(object)content, "Last restock");
				RectTransform val6 = MenuVisuals.Rect((Transform)(object)parent5, "RestockSummary");
				Height(((Component)val6).gameObject, 76f);
				TextMeshProUGUI summaryText = MenuVisuals.Text((Transform)(object)val6, workingHoursText, "", 17f);
				int page = 0;
				RectTransform val7 = MenuVisuals.Rect((Transform)(object)parent5, "RestockDecisions");
				Height(((Component)val7).gameObject, 140f);
				TextMeshProUGUI reportText = MenuVisuals.Text((Transform)(object)val7, workingHoursText, "", 18f);
				RectTransform val8 = MenuVisuals.Rect((Transform)(object)parent5, "ReportPages");
				Height(((Component)val8).gameObject, 46f);
				TextMeshProUGUI pageText = MenuVisuals.Text((Transform)(object)val8, workingHoursText, "", 18f);
				((TMP_Text)pageText).alignment = (TextAlignmentOptions)514;
				int[] array2 = new int[2] { -1, 1 };
				foreach (int direction in array2)
				{
					Button val9 = Button(Owner.hireButton, (Transform)(object)val8, (direction < 0) ? "PREVIOUS" : "NEXT", delegate
					{
						page += direction;
						ShowPage();
					});
					RectTransform component3 = ((Component)val9).GetComponent<RectTransform>();
					component3.anchorMin = new Vector2((direction < 0) ? 0f : 0.7f, 0f);
					component3.anchorMax = new Vector2((direction < 0) ? 0.3f : 1f, 1f);
					Vector2 offsetMin = (component3.offsetMax = Vector2.zero);
					component3.offsetMin = offsetMin;
					controls.Add((Selectable)(object)val9);
					AutoScroll((Selectable)(object)val9);
				}
				refresh.Add(ShowPage);
				RectTransform val10 = MenuVisuals.Rect(root.transform, "Actions");
				Place(val10, 20f, 10f, 20f, 38f, top: false);
				Button[] array3 = (Button[])(object)new Button[3]
				{
					Button(Owner.hireButton, (Transform)(object)val10, "APPLY", Commit),
					Button(Owner.hireButton, (Transform)(object)val10, "CANCEL", Close),
					Button(Owner.hireButton, (Transform)(object)val10, "RESTORE DEFAULTS", delegate
					{
						draft = new ManagerPolicy();
						sharedDraft = new SharedBudgetPolicy();
						Changed();
					})
				};
				for (int num3 = 0; num3 < array3.Length; num3++)
				{
					RectTransform component4 = ((Component)array3[num3]).GetComponent<RectTransform>();
					component4.anchorMin = new Vector2((float)num3 / 3f, 0f);
					component4.anchorMax = new Vector2((float)(num3 + 1) / 3f, 1f);
					component4.offsetMin = new Vector2(4f, 0f);
					component4.offsetMax = new Vector2(-4f, 0f);
					controls.Add((Selectable)(object)array3[num3]);
				}
				status = MenuVisuals.Text(root.transform, workingHoursText, applied, 15f);
				Place(((TMP_Text)status).rectTransform, 20f, 50f, 20f, 40f, top: false);
				AddScrollbar();
				foreach (TextMeshProUGUI componentsInChild in root.GetComponentsInChildren<TextMeshProUGUI>(true))
				{
					if ((Object)(object)componentsInChild != (Object)(object)val2)
					{
						((Graphic)componentsInChild).color = new Color(0.9f, 0.88f, 0.82f);
					}
				}
				foreach (Selectable item2 in ((IEnumerable<Selectable>)((Component)Owner._window).GetComponentsInChildren<Selectable>(true)).Where((Selectable c) => !((Component)c).transform.IsChildOf(root.transform)))
				{
					disabled.Add((item2, item2.interactable));
					item2.interactable = false;
				}
				staffSurface = ((Component)Owner).GetComponent<CanvasGroup>();
				if ((Object)(object)staffSurface != (Object)null)
				{
					staffAlpha = staffSurface.alpha;
					staffInteractable = staffSurface.interactable;
					staffRaycasts = staffSurface.blocksRaycasts;
					staffSurface.alpha = 0f;
					CanvasGroup? obj4 = staffSurface;
					interactable = (staffSurface.blocksRaycasts = false);
					obj4.interactable = interactable;
				}
				root.SetActive(true);
				CanvasBehaviourManager.RegisterRuntimeChildren(root, ref panelCanvas);
				RefreshScrollRouting();
				Changed(edit: false);
				Reflow();
				scroll.verticalNormalizedPosition = 1f;
				controls[0].Select();
				void ShowPage()
				{
					if (!ManagerPolicies.Reports.TryGetValue(((BaseProperty)venue).Guid, out RestockReport value))
					{
						((TMP_Text)summaryText).text = "No restock recorded in this session.";
						((TMP_Text)reportText).text = "Purchases and funding decisions will appear after a manager attempts an order.";
						((TMP_Text)pageText).text = "1 / 1";
					}
					else
					{
						long num4 = Math.Max(0L, TimeOfDayManager.TotalGameSeconds - value.Time);
						((TMP_Text)summaryText).text = $"{value.Summary}\n{num4 / 3600}h {num4 % 3600 / 60}m ago in game · {(value.Failed ? "Order incomplete — inspect the mod log" : "Restock finished")}";
						int num5 = Math.Max(1, (value.Lines.Count + 1) / 2);
						page = Math.Clamp(page, 0, num5 - 1);
						((TMP_Text)reportText).text = string.Join("\n\n", value.Lines.Skip(page * 2).Take(2));
						((TMP_Text)pageText).text = $"{page + 1} / {num5}";
					}
				}
			}

			internal void RouteScroll(UIWindow window, List<ScrollRect> results)
			{
				if (!((Object)(object)root == (Object)null) && !((Object)(object)Owner._window != (Object)(object)window))
				{
					results.Clear();
					results.Add(scroll);
				}
			}

			private void RefreshScrollRouting()
			{
				if ((Object)(object)Owner == (Object)null || (Object)(object)Owner._window == (Object)null)
				{
					return;
				}
				UIScrollViewHandler val = Object.FindObjectOfType<UIScrollViewHandler>();
				if (!((Object)(object)val == (Object)null))
				{
					IScrollRectsProvider val2 = ((Il2CppObjectBase)Owner._window).Cast<IScrollRectsProvider>();
					val._scrollRectCache.Remove(val2);
					if (val._focusedWindow != null && ((Il2CppObjectBase)val._focusedWindow).Pointer == ((Il2CppObjectBase)val2).Pointer)
					{
						val._focusedScrollRects = val.GetScrollRects(val2);
					}
				}
			}

			private void AddScrollbar()
			{
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0055: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				RectTransform obj = MenuVisuals.Rect(root.transform, "VerticalScrollbar");
				obj.anchorMin = new Vector2(1f, 0f);
				obj.anchorMax = Vector2.one;
				obj.offsetMin = new Vector2(-36f, 96f);
				obj.offsetMax = new Vector2(-20f, -88f);
				((Graphic)((Component)obj).gameObject.AddComponent<Image>()).color = new Color(0.18f, 0.17f, 0.15f, 1f);
				RectTransform val = MenuVisuals.Rect((Transform)(object)obj, "Handle");
				Image val2 = ((Component)val).gameObject.AddComponent<Image>();
				((Graphic)val2).color = new Color(0.77f, 0.64f, 0.44f, 1f);
				Scrollbar val3 = ((Component)obj).gameObject.AddComponent<Scrollbar>();
				val3.handleRect = val;
				((Selectable)val3).targetGraphic = (Graphic)(object)val2;
				val3.direction = (Direction)2;
				scroll.verticalScrollbar = val3;
				scroll.verticalScrollbarVisibility = (ScrollbarVisibility)0;
				controls.Add((Selectable)(object)val3);
			}

			private void DishRow(Transform parent, string label, Func<int> value, Action<int> adjust)
			{
				//IL_005c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Unknown result type (might be due to invalid IL or missing references)
				//IL_0153: Unknown result type (might be due to invalid IL or missing references)
				//IL_0168: Unknown result type (might be due to invalid IL or missing references)
				//IL_0187: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_0240: Unknown result type (might be due to invalid IL or missing references)
				//IL_024b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0268: Unknown result type (might be due to invalid IL or missing references)
				//IL_0284: Unknown result type (might be due to invalid IL or missing references)
				RectTransform obj = MenuVisuals.Rect(parent, "Dish