Decompiled source of Airport Remixed v3.0.0

tony4twentys.Airport_Remixed.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyTitle("Airport Remixed")]
[assembly: AssemblyDescription("A BepInEx plugin for PEAK that remixes airport functionality")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("tony4twentys")]
[assembly: AssemblyProduct("Airport Remixed")]
[assembly: AssemblyCopyright("Copyright © tony4twentys 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3d39d492-4184-4d83-8b4a-1227283ca458")]
[assembly: AssemblyFileVersion("3.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("3.0.0.0")]
[module: UnverifiableCode]
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace tony4twentys.Airport_Remixed
{
	[BepInPlugin("tony4twentys.Airport_Remixed", "Airport Remixed", "3.0.0")]
	[BepInProcess("PEAK.exe")]
	public class AirportRemixedPlugin : BaseUnityPlugin
	{
		public static ManualLogSource Logger;

		private const float MirrorCamToggleDuration = 20f;

		private ConfigEntry<KeyCode> muralModeModifierKey;

		private ConfigEntry<KeyCode> muralModeMainKey;

		private ConfigEntry<bool> muralModeRequireModifier;

		private bool isAirportScene;

		private bool holdLayoutForEditor;

		private bool mirrorCamToggled;

		private float mirrorCamToggleTime;

		private void Awake()
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Logger = ((BaseUnityPlugin)this).Logger;
			Logger.LogInfo((object)"Plugin tony4twentys.Airport_Remixed is loaded.");
			BindConfig();
			new Harmony("tony4twentys.Airport_Remixed.menu").PatchAll();
		}

		private void BindConfig()
		{
			muralModeRequireModifier = ((BaseUnityPlugin)this).Config.Bind<bool>("MuralMode", "RequireModifierKey", true, "Whether MuralMode requires a modifier key to be held down");
			muralModeModifierKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("MuralMode", "ModifierKey", (KeyCode)308, "The modifier key for MuralMode (only used if RequireModifierKey is true)");
			muralModeMainKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("MuralMode", "MainKey", (KeyCode)112, "The main key to trigger MuralMode");
		}

		private void OnEnable()
		{
			SceneManager.sceneLoaded += OnSceneLoaded;
		}

		private void OnDisable()
		{
			SceneManager.sceneLoaded -= OnSceneLoaded;
			ResetAirportState();
		}

		private void Update()
		{
			if (CheckMuralModeKey())
			{
				ToggleMirrorCam();
			}
			AirportMoveRuntime.Tick();
			if (mirrorCamToggled && Time.time - mirrorCamToggleTime >= 20f)
			{
				RestoreMirrorCam();
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			isAirportScene = ((Scene)(ref scene)).name == "Airport";
			ResetAirportState();
			if (isAirportScene)
			{
				holdLayoutForEditor = AirportLayoutLoader.IsAirportEditorLoaded();
				if (holdLayoutForEditor)
				{
					Logger.LogInfo((object)"Airport editor is loaded — leaving vanilla. The editor loads Parents projects.");
				}
				else
				{
					((MonoBehaviour)this).StartCoroutine(ApplyLayoutRoutine());
				}
			}
		}

		private void OnGUI()
		{
			AirportLayoutLoadFlow.OnGUI();
		}

		private void ResetAirportState()
		{
			((MonoBehaviour)this).StopAllCoroutines();
			AirportLayoutLoadFlow.Cancel();
			mirrorCamToggled = false;
			AirportMoveRuntime.Clear();
		}

		private IEnumerator ApplyLayoutRoutine()
		{
			IEnumerator steps = AirportLayoutLoadFlow.Run();
			while (true)
			{
				object current;
				try
				{
					if (!steps.MoveNext())
					{
						break;
					}
					current = steps.Current;
				}
				catch (Exception ex)
				{
					AirportLayoutLoadFlow.Cancel();
					Logger.LogError((object)("Failed to apply airport layout: " + ex.Message));
					break;
				}
				yield return current;
			}
		}

		private bool CheckMuralModeKey()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			if (!Input.GetKeyDown(muralModeMainKey.Value))
			{
				return false;
			}
			if (muralModeRequireModifier.Value)
			{
				return Input.GetKey(muralModeModifierKey.Value);
			}
			return true;
		}

		private void ToggleMirrorCam()
		{
			GameObject val = GameObject.Find("Map/Mirror (1)/Mirror Cam");
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"Mirror Cam not found at path: Map/Mirror (1)/Mirror Cam");
				return;
			}
			val.SetActive(false);
			mirrorCamToggled = true;
			mirrorCamToggleTime = Time.time;
		}

		private void RestoreMirrorCam()
		{
			GameObject val = GameObject.Find("Map/Mirror (1)/Mirror Cam");
			if (!((Object)(object)val == (Object)null))
			{
				val.SetActive(true);
				mirrorCamToggled = false;
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "tony4twentys.Airport_Remixed";

		public const string PLUGIN_NAME = "Airport Remixed";

		public const string PLUGIN_VERSION = "3.0.0";
	}
	[Serializable]
	public class AirportLayoutFile
	{
		public const string CurrentVersion = "5";

		public string version = "5";

		public LayoutBehavior[] behaviors;

		public LayoutTrigger[] triggers;

		public LayoutFunction[] functions;

		public LayoutPlacement[] placements;

		public static AirportLayoutFile Parse(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return null;
			}
			if (json[0] == '\ufeff')
			{
				json = json.Substring(1);
			}
			AirportLayoutFile airportLayoutFile = new AirportLayoutFile();
			if (TryParseFunctions(json, out var array, out var hasKey) && hasKey)
			{
				airportLayoutFile.functions = array ?? new LayoutFunction[0];
			}
			return airportLayoutFile;
		}

		public static bool TryParseFunctions(string json, out LayoutFunction[] functions, out bool hasKey)
		{
			functions = null;
			hasKey = false;
			if (string.IsNullOrEmpty(json))
			{
				return false;
			}
			int num = json.IndexOf("\"functions\"", StringComparison.Ordinal);
			if (num < 0)
			{
				return false;
			}
			hasKey = true;
			int num2 = json.IndexOf('[', num);
			if (num2 < 0)
			{
				functions = new LayoutFunction[0];
				return true;
			}
			int num3 = MatchingBracket(json, num2);
			if (num3 < 0)
			{
				functions = new LayoutFunction[0];
				return true;
			}
			List<string> list = TopLevelObjects(json.Substring(num2, num3 - num2 + 1));
			List<LayoutFunction> list2 = new List<LayoutFunction>(list.Count);
			for (int i = 0; i < list.Count; i++)
			{
				LayoutFunction layoutFunction = ParseOneFunction(list[i]);
				if (layoutFunction != null && !string.IsNullOrEmpty(layoutFunction.id))
				{
					list2.Add(layoutFunction);
				}
			}
			functions = list2.ToArray();
			return true;
		}

		private static LayoutFunction ParseOneFunction(string objectJson)
		{
			LayoutFunction layoutFunction = JsonUtility.FromJson<LayoutFunction>(objectJson);
			if (layoutFunction == null)
			{
				return null;
			}
			LayoutStep[] array = ParseSteps(objectJson);
			if (array.Length != 0 || layoutFunction.steps == null)
			{
				layoutFunction.steps = array;
			}
			else
			{
				FillMissingPoses(layoutFunction.steps, objectJson);
			}
			layoutFunction.states = ParseStates(objectJson, layoutFunction.states);
			layoutFunction.buttons = ParseButtons(objectJson, layoutFunction.buttons);
			return layoutFunction;
		}

		private static LayoutStep[] ParseSteps(string json)
		{
			string text = ExtractNamedArray(json, "steps");
			if (string.IsNullOrEmpty(text))
			{
				return new LayoutStep[0];
			}
			List<string> list = TopLevelObjects(text);
			List<LayoutStep> list2 = new List<LayoutStep>(list.Count);
			for (int i = 0; i < list.Count; i++)
			{
				LayoutStep layoutStep = JsonUtility.FromJson<LayoutStep>(list[i]);
				if (layoutStep != null)
				{
					LayoutPose[] array = ParsePoses(list[i]);
					if (array.Length != 0 || layoutStep.poses == null)
					{
						layoutStep.poses = array;
					}
					list2.Add(layoutStep);
				}
			}
			return list2.ToArray();
		}

		private static LayoutPose[] ParsePoses(string stepJson)
		{
			string text = ExtractNamedArray(stepJson, "poses");
			if (string.IsNullOrEmpty(text))
			{
				return new LayoutPose[0];
			}
			List<string> list = TopLevelObjects(text);
			List<LayoutPose> list2 = new List<LayoutPose>(list.Count);
			for (int i = 0; i < list.Count; i++)
			{
				LayoutPose layoutPose = JsonUtility.FromJson<LayoutPose>(list[i]);
				if (layoutPose != null)
				{
					list2.Add(layoutPose);
				}
			}
			return list2.ToArray();
		}

		private static void FillMissingPoses(LayoutStep[] steps, string functionJson)
		{
			if (steps == null || steps.Length == 0)
			{
				return;
			}
			string text = ExtractNamedArray(functionJson, "steps");
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			List<string> list = TopLevelObjects(text);
			int num = Mathf.Min(steps.Length, list.Count);
			for (int i = 0; i < num; i++)
			{
				if (steps[i] != null && (steps[i].poses == null || steps[i].poses.Length == 0))
				{
					steps[i].poses = ParsePoses(list[i]);
				}
			}
		}

		private static LayoutFnState[] ParseStates(string functionJson, LayoutFnState[] fallback)
		{
			string text = ExtractNamedArray(functionJson, "states");
			if (string.IsNullOrEmpty(text))
			{
				return fallback ?? new LayoutFnState[0];
			}
			List<string> list = TopLevelObjects(text);
			if (list.Count == 0)
			{
				return fallback ?? new LayoutFnState[0];
			}
			List<LayoutFnState> list2 = new List<LayoutFnState>(list.Count);
			for (int i = 0; i < list.Count; i++)
			{
				LayoutFnState layoutFnState = JsonUtility.FromJson<LayoutFnState>(list[i]);
				if (layoutFnState != null)
				{
					LayoutStep[] array = ParseSteps(list[i]);
					if (array.Length != 0 || layoutFnState.steps == null)
					{
						layoutFnState.steps = array;
					}
					list2.Add(layoutFnState);
				}
			}
			return list2.ToArray();
		}

		private static LayoutMenuButton[] ParseButtons(string functionJson, LayoutMenuButton[] fallback)
		{
			string text = ExtractNamedArray(functionJson, "buttons");
			if (string.IsNullOrEmpty(text))
			{
				return fallback ?? new LayoutMenuButton[0];
			}
			List<string> list = TopLevelObjects(text);
			if (list.Count == 0)
			{
				return fallback ?? new LayoutMenuButton[0];
			}
			List<LayoutMenuButton> list2 = new List<LayoutMenuButton>(list.Count);
			for (int i = 0; i < list.Count; i++)
			{
				LayoutMenuButton layoutMenuButton = JsonUtility.FromJson<LayoutMenuButton>(list[i]);
				if (layoutMenuButton != null)
				{
					LayoutStep[] array = ParseSteps(list[i]);
					if (array.Length != 0 || layoutMenuButton.steps == null)
					{
						layoutMenuButton.steps = array;
					}
					list2.Add(layoutMenuButton);
				}
			}
			return list2.ToArray();
		}

		private static string ExtractNamedArray(string json, string name)
		{
			int num = json.IndexOf("\"" + name + "\"", StringComparison.Ordinal);
			if (num < 0)
			{
				return null;
			}
			int num2 = json.IndexOf('[', num);
			if (num2 < 0)
			{
				return null;
			}
			int num3 = MatchingBracket(json, num2);
			if (num3 < 0)
			{
				return null;
			}
			return json.Substring(num2, num3 - num2 + 1);
		}

		private static List<string> TopLevelObjects(string arrayJson)
		{
			List<string> list = new List<string>();
			if (string.IsNullOrEmpty(arrayJson))
			{
				return list;
			}
			int i;
			for (i = 0; i < arrayJson.Length && arrayJson[i] != '['; i++)
			{
			}
			i++;
			while (i < arrayJson.Length)
			{
				switch (arrayJson[i])
				{
				default:
					i++;
					continue;
				case '{':
				{
					int num = MatchingBrace(arrayJson, i);
					if (num >= 0)
					{
						list.Add(arrayJson.Substring(i, num - i + 1));
						i = num + 1;
						continue;
					}
					break;
				}
				case ']':
					break;
				}
				break;
			}
			return list;
		}

		private static int MatchingBrace(string json, int open)
		{
			int num = 0;
			bool flag = false;
			bool flag2 = false;
			for (int i = open; i < json.Length; i++)
			{
				char c = json[i];
				if (flag)
				{
					if (flag2)
					{
						flag2 = false;
						continue;
					}
					switch (c)
					{
					case '\\':
						flag2 = true;
						break;
					case '"':
						flag = false;
						break;
					}
					continue;
				}
				switch (c)
				{
				case '"':
					flag = true;
					break;
				case '{':
					num++;
					break;
				case '}':
					num--;
					if (num == 0)
					{
						return i;
					}
					break;
				}
			}
			return -1;
		}

		public static string WithoutPlacements(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return json;
			}
			int num = json.IndexOf("\"functions\"", StringComparison.Ordinal);
			if (num < 0)
			{
				return json;
			}
			int num2 = json.IndexOf('[', num);
			if (num2 < 0)
			{
				return json;
			}
			int num3 = MatchingBracket(json, num2);
			if (num3 < 0)
			{
				return json;
			}
			return json.Substring(0, num3 + 1) + "\n}";
		}

		private static int MatchingBracket(string json, int open)
		{
			int num = 0;
			bool flag = false;
			bool flag2 = false;
			for (int i = open; i < json.Length; i++)
			{
				char c = json[i];
				if (flag)
				{
					if (flag2)
					{
						flag2 = false;
						continue;
					}
					switch (c)
					{
					case '\\':
						flag2 = true;
						break;
					case '"':
						flag = false;
						break;
					}
					continue;
				}
				switch (c)
				{
				case '"':
					flag = true;
					break;
				case '[':
					num++;
					break;
				case ']':
					num--;
					if (num == 0)
					{
						return i;
					}
					break;
				}
			}
			return -1;
		}
	}
	[Serializable]
	public class LayoutBehavior
	{
		public string id;

		public string kind;

		public string target;

		public string targetId;

		public bool enabled = true;

		public string component;

		public string member;

		public string text;

		public string extra;

		public Vector3 vector;

		public Vector3 start;

		public Vector3 end;

		public Vector3 startEuler;

		public Vector3 endEuler;

		public float number;

		public bool flag;
	}
	[Serializable]
	public class LayoutTrigger
	{
		public string id;

		public string target;

		public string targetId;

		public bool enabled = true;

		public string kind = "prompt";

		public string mode = "cycle";

		public string prompt = "Open";

		public float speed = 1f;

		public int startStop;

		public LayoutStop[] stops;
	}
	[Serializable]
	public class LayoutStop
	{
		public string id;

		public string name;

		public string prompt;

		public string menuLabel;

		public Vector3 position;

		public Vector3 euler;
	}
	[Serializable]
	public class LayoutFunction
	{
		public string id;

		public string kind = "menu";

		public string target;

		public string targetId;

		public bool enabled = true;

		public string name = "Menu";

		public string triggerKind = "prompt";

		public string title;

		public string prompt = "Open";

		public string listenButtonId;

		public string action = "none";

		public string actionMenuId;

		public Vector3 end;

		public Vector3 endEuler;

		public Vector3 endScale;

		public bool hasEnd;

		public float speed = 1f;

		public bool loop;

		public int loopCount;

		public bool random;

		public LayoutStep[] steps;

		public LayoutFnState[] states;

		public int startState;

		public LayoutMenuButton[] buttons;
	}
	[Serializable]
	public class LayoutFnState
	{
		public string id;

		public string name = "State";

		public string title;

		public string prompt = "Open";

		public LayoutStep[] steps;

		public int next = -1;

		public float autoAfter;
	}
	[Serializable]
	public class LayoutMenuButton
	{
		public string id;

		public string label = "Button";

		public string action = "none";

		public string actionMenuId;

		public string target;

		public string targetId;

		public Vector3 end;

		public Vector3 endEuler;

		public bool hasEnd;

		public float speed = 1f;

		public LayoutStep[] steps;
	}
	[Serializable]
	public class LayoutStep
	{
		public string kind = "move";

		public float delay;

		public float speed = 1f;

		public bool random;

		public string actionMenuId;

		public string clipName;

		public string animTarget;

		public string animTargetId;

		public bool together;

		public string material;

		public bool flag;

		public bool uninterruptible;

		public bool easeIn;

		public bool easeOut;

		public bool curve;

		public bool facePath;

		public float tilt;

		public float bend = 1f;

		public float lifetime;

		public string spawnId;

		public LayoutPose[] poses;
	}
	[Serializable]
	public class LayoutPose
	{
		public Vector3 position;

		public Vector3 euler;

		public Vector3 scale;

		public bool hasScale;

		public string target;

		public string targetId;

		public string material;

		public bool setColor;

		public Color color;

		public bool setUv;

		public Vector2 tile = Vector2.one;

		public Vector2 offset;
	}
	[Serializable]
	public class LayoutPlacement
	{
		public string id;

		public string group;

		public string op;

		public string source;

		public string parent;

		public string name;

		public bool setPosition;

		public Vector3 position;

		public bool setRotation;

		public Vector3 euler;

		public bool setScale;

		public Vector3 scale;

		public string material;

		public string texture;

		public bool setTexture;

		public bool setColor;

		public Color color;

		public bool setUv;

		public Vector2 tile = Vector2.one;

		public Vector2 offset;

		public bool setActive;

		public bool active = true;

		public bool solid;
	}
	internal static class AirportPhotoboothLoad
	{
		private const string BoothPath = "Map/Photobooth";

		private const string MenuScreenPath = "Airport Remixed/AR_Main/AR_Photobooth_Stuff/Screen";

		private static Quaternion _vanillaRotation = Quaternion.identity;

		private static bool _captured;

		internal static void CaptureVanilla()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			_captured = false;
			_vanillaRotation = Quaternion.identity;
			GameObject val = AirportLayoutLoader.FindSceneObject("Map/Photobooth");
			if (!((Object)(object)val == (Object)null))
			{
				_vanillaRotation = val.transform.rotation;
				_captured = true;
			}
		}

		internal static GameObject FindMenuScreen()
		{
			GameObject val = AirportLayoutLoader.FindSceneObject("Airport Remixed/AR_Main/AR_Photobooth_Stuff/Screen");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			AirportRemixedPiece[] array = Object.FindObjectsByType<AirportRemixedPiece>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null && string.Equals(array[i].id, "edit-335759fb", StringComparison.Ordinal))
				{
					return ((Component)array[i]).gameObject;
				}
			}
			return null;
		}

		internal static bool IsOccupied(AirportPhotoboothKiosk kiosk, Vector3 worldPoint)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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)
			if (IsInsideBooth(worldPoint))
			{
				return true;
			}
			if ((Object)(object)kiosk == (Object)null || (Object)(object)kiosk.insidePlaneTf == (Object)null)
			{
				return false;
			}
			GameObject val = AirportLayoutLoader.FindSceneObject("Map/Photobooth");
			if ((Object)(object)val != (Object)null)
			{
				Vector3 val2 = kiosk.insidePlaneTf.position - val.transform.position;
				if (((Vector3)(ref val2)).sqrMagnitude > 144f)
				{
					return false;
				}
			}
			if (worldPoint.x < kiosk.insidePlaneTf.position.x)
			{
				return true;
			}
			return IsCharacterInside(kiosk, worldPoint);
		}

		internal static bool IsCharacterInside(AirportPhotoboothKiosk kiosk, Vector3 worldPoint)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//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)
			if ((Object)(object)kiosk == (Object)null || (Object)(object)kiosk.insidePlaneTf == (Object)null)
			{
				return false;
			}
			GameObject val = AirportLayoutLoader.FindSceneObject("Map/Photobooth");
			Transform obj = (((Object)(object)val != (Object)null) ? val.transform : ((Component)kiosk).transform);
			Quaternion val2 = (_captured ? _vanillaRotation : Quaternion.identity);
			Vector3 val3 = obj.rotation * Quaternion.Inverse(val2) * Vector3.right;
			if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f)
			{
				val3 = Vector3.right;
			}
			return Vector3.Dot(worldPoint - kiosk.insidePlaneTf.position, val3) < 0f;
		}

		internal static bool IsRemixedMenuScreen(GameObject screen)
		{
			if ((Object)(object)screen == (Object)null)
			{
				return false;
			}
			Transform val = screen.transform;
			while ((Object)(object)val != (Object)null)
			{
				if (((Object)val).name == "Airport Remixed")
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		internal static void KeepMenuScreenOn(AirportPhotoboothKiosk kiosk)
		{
			GameObject val = FindMenuScreen();
			if (!((Object)(object)val == (Object)null))
			{
				if ((Object)(object)kiosk != (Object)null && ((Object)(object)kiosk.screen == (Object)null || (Object)(object)kiosk.screen != (Object)(object)val))
				{
					kiosk.screen = val;
				}
				if (!val.activeSelf)
				{
					val.SetActive(true);
				}
			}
		}

		private static bool IsInsideBooth(Vector3 worldPoint)
		{
			//IL_001c: 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_002c: 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)
			//IL_00b5: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: 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_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = AirportLayoutLoader.FindSceneObject("Map/Photobooth");
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Vector3 position = val.transform.position;
			Renderer[] componentsInChildren = val.GetComponentsInChildren<Renderer>(true);
			Bounds val2 = default(Bounds);
			bool flag = false;
			foreach (Renderer val3 in componentsInChildren)
			{
				if ((Object)(object)val3 == (Object)null || !val3.enabled)
				{
					continue;
				}
				Vector3 val4 = ((Component)val3).transform.position - position;
				if (!(((Vector3)(ref val4)).sqrMagnitude > 100f) && !IsKioskBranch(((Component)val3).transform))
				{
					if (!flag)
					{
						val2 = val3.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val2)).Encapsulate(val3.bounds);
					}
				}
			}
			if (!flag)
			{
				((Bounds)(ref val2))..ctor(position + Vector3.up * 1.8f, new Vector3(4.5f, 4f, 4.5f));
				return ((Bounds)(ref val2)).Contains(worldPoint);
			}
			((Bounds)(ref val2)).Expand(1.25f);
			return ((Bounds)(ref val2)).Contains(worldPoint);
		}

		private static bool IsKioskBranch(Transform t)
		{
			while ((Object)(object)t != (Object)null)
			{
				if ((((Object)t).name ?? string.Empty).StartsWith("Kiosk", StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
				t = t.parent;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(AirportPhotoboothKiosk), "Update")]
	internal static class Patch_PhotoboothInside
	{
		private static bool _logged;

		private static void Postfix(AirportPhotoboothKiosk __instance)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					AirportPhotoboothLoad.KeepMenuScreenOn(__instance);
					Character localCharacter = Character.localCharacter;
					bool enabled = (__instance.inPhotobooth = (Object)(object)localCharacter != (Object)null && AirportPhotoboothLoad.IsOccupied(__instance, localCharacter.Center));
					if ((Object)(object)__instance.displayCamera != (Object)null)
					{
						((Behaviour)__instance.displayCamera).enabled = enabled;
					}
				}
			}
			catch (Exception ex)
			{
				if (!_logged)
				{
					_logged = true;
					ManualLogSource logger = AirportRemixedPlugin.Logger;
					if (logger != null)
					{
						logger.LogError((object)("Photobooth Update failed: " + ex));
					}
				}
			}
		}
	}
	internal static class AirportUi
	{
		private static readonly Color ButtonColor = new Color(0.1792453f, 0.1253449f, 0.09046815f, 62f / 85f);

		private static readonly Color ButtonHover = new Color(0.26f, 0.18f, 0.13f, 0.92f);

		private static readonly Color Accent = new Color(0.55f, 0.42f, 0.22f, 0.95f);

		private static readonly Color Cream = new Color(0.95f, 0.93f, 0.88f, 1f);

		private static GameObject _buttonDonor;

		private static TMP_FontAsset _cachedFont;

		internal static Button CreatePeakButton(Transform parent, string label, UnityAction onClick)
		{
			GameObject val = TryClonePauseButton(parent, label) ?? CreatePlainButton(parent, label);
			LayoutElement obj = val.GetComponent<LayoutElement>() ?? val.AddComponent<LayoutElement>();
			obj.minHeight = 34f;
			obj.preferredHeight = 34f;
			obj.flexibleWidth = 1f;
			NormalizeLabel(val, label);
			Button val2 = val.GetComponent<Button>() ?? val.AddComponent<Button>();
			((UnityEventBase)val2.onClick).RemoveAllListeners();
			if (onClick != null)
			{
				((UnityEvent)val2.onClick).AddListener(onClick);
			}
			Canvas.ForceUpdateCanvases();
			return val2;
		}

		internal static void ApplyFont(TextMeshProUGUI text)
		{
			if (!((Object)(object)text == (Object)null))
			{
				TMP_FontAsset gameFont = GetGameFont();
				if ((Object)(object)gameFont != (Object)null)
				{
					((TMP_Text)text).font = gameFont;
				}
			}
		}

		private static GameObject TryClonePauseButton(Transform parent, string label)
		{
			try
			{
				GameObject val = ResolveButtonDonor();
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				GameObject val2 = Object.Instantiate<GameObject>(val, parent, false);
				((Object)val2).name = "AR_Btn_" + Sanitize(label);
				val2.SetActive(true);
				LocalizedText[] componentsInChildren = val2.GetComponentsInChildren<LocalizedText>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					if ((Object)(object)componentsInChildren[i] != (Object)null)
					{
						((Behaviour)componentsInChildren[i]).enabled = false;
					}
				}
				return val2;
			}
			catch
			{
				_buttonDonor = null;
				return null;
			}
		}

		private static GameObject ResolveButtonDonor()
		{
			if ((Object)(object)_buttonDonor != (Object)null)
			{
				return _buttonDonor;
			}
			try
			{
				PauseMenuMainPage val = (((Object)(object)GUIManager.instance != (Object)null) ? GUIManager.instance.pauseMenuMainPage : null);
				if ((Object)(object)val == (Object)null)
				{
					val = Object.FindFirstObjectByType<PauseMenuMainPage>((FindObjectsInactive)1);
				}
				Button val2 = (((Object)(object)val != (Object)null) ? (val.m_resumeButton ?? val.m_settingsButton ?? val.m_quitButton) : null);
				if ((Object)(object)val2 != (Object)null)
				{
					_buttonDonor = ((Component)val2).gameObject;
				}
			}
			catch
			{
			}
			return _buttonDonor;
		}

		private static GameObject CreatePlainButton(Transform parent, string label)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			//IL_0065: 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_0085: 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_009d: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: 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_00f9: 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_012e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("AR_Btn_" + Sanitize(label), new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = ButtonColor;
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			ColorBlock colors = ((Selectable)component2).colors;
			((ColorBlock)(ref colors)).normalColor = ButtonColor;
			((ColorBlock)(ref colors)).highlightedColor = ButtonHover;
			((ColorBlock)(ref colors)).pressedColor = Accent;
			((Selectable)component2).colors = colors;
			GameObject val2 = new GameObject("Text", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent(val.transform, false);
			RectTransform component3 = val2.GetComponent<RectTransform>();
			component3.anchorMin = Vector2.zero;
			component3.anchorMax = Vector2.one;
			component3.offsetMin = Vector2.zero;
			component3.offsetMax = Vector2.zero;
			TextMeshProUGUI obj = val2.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).text = label ?? string.Empty;
			((TMP_Text)obj).alignment = (TextAlignmentOptions)514;
			((Graphic)obj).color = Cream;
			ApplyFont(obj);
			return val;
		}

		private static void NormalizeLabel(GameObject button, string label)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			HorizontalOrVerticalLayoutGroup component = button.GetComponent<HorizontalOrVerticalLayoutGroup>();
			if ((Object)(object)component != (Object)null)
			{
				((LayoutGroup)component).childAlignment = (TextAnchor)4;
				((LayoutGroup)component).padding = new RectOffset(8, 8, 2, 2);
				component.childForceExpandWidth = true;
				component.childForceExpandHeight = true;
			}
			ContentSizeFitter component2 = button.GetComponent<ContentSizeFitter>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.horizontalFit = (FitMode)0;
			}
			TextMeshProUGUI[] componentsInChildren = button.GetComponentsInChildren<TextMeshProUGUI>(true);
			foreach (TextMeshProUGUI val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				((Component)val).gameObject.SetActive(true);
				((Behaviour)val).enabled = true;
				((TMP_Text)val).text = label ?? string.Empty;
				((TMP_Text)val).alignment = (TextAlignmentOptions)514;
				((Graphic)val).color = Cream;
				((TMP_Text)val).enableAutoSizing = true;
				((TMP_Text)val).fontSizeMin = 11f;
				((TMP_Text)val).fontSizeMax = 20f;
				((TMP_Text)val).overflowMode = (TextOverflowModes)1;
				((TMP_Text)val).enableWordWrapping = false;
				ApplyFont(val);
				Transform val2 = ((TMP_Text)val).transform;
				while ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)button.transform)
				{
					((Component)val2).gameObject.SetActive(true);
					RectTransform val3 = (RectTransform)(object)((val2 is RectTransform) ? val2 : null);
					if ((Object)(object)val3 != (Object)null)
					{
						bool flag = (Object)(object)val2 == (Object)(object)((TMP_Text)val).transform;
						Stretch(val3, flag ? 8f : 0f, flag ? 2f : 0f);
					}
					ContentSizeFitter component3 = ((Component)val2).GetComponent<ContentSizeFitter>();
					if ((Object)(object)component3 != (Object)null)
					{
						component3.horizontalFit = (FitMode)0;
					}
					val2 = val2.parent;
				}
			}
		}

		private static void Stretch(RectTransform rt, float padX, float padY)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.offsetMin = new Vector2(padX, padY);
			rt.offsetMax = new Vector2(0f - padX, 0f - padY);
		}

		private static TMP_FontAsset GetGameFont()
		{
			if ((Object)(object)_cachedFont != (Object)null)
			{
				return _cachedFont;
			}
			try
			{
				if ((Object)(object)GUIManager.instance != (Object)null)
				{
					TextMeshProUGUI componentInChildren = ((Component)GUIManager.instance).GetComponentInChildren<TextMeshProUGUI>(true);
					if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((TMP_Text)componentInChildren).font != (Object)null)
					{
						_cachedFont = ((TMP_Text)componentInChildren).font;
						return _cachedFont;
					}
				}
				TextMeshProUGUI val = Object.FindFirstObjectByType<TextMeshProUGUI>((FindObjectsInactive)1);
				if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null)
				{
					_cachedFont = ((TMP_Text)val).font;
				}
			}
			catch
			{
			}
			return _cachedFont;
		}

		private static string Sanitize(string s)
		{
			if (string.IsNullOrEmpty(s))
			{
				return "Btn";
			}
			char[] array = s.ToCharArray();
			for (int i = 0; i < array.Length; i++)
			{
				if (!char.IsLetterOrDigit(array[i]))
				{
					array[i] = '_';
				}
			}
			return new string(array);
		}
	}
	internal static class AirportPickupLoad
	{
		private struct SavedPickup
		{
			public string path;

			public Vector3 position;

			public Vector3 euler;

			public Vector3 scale;

			public bool active;
		}

		private static readonly List<SavedPickup> Saved = new List<SavedPickup>();

		internal static void Clear()
		{
			Saved.Clear();
		}

		internal static void Remember(string path, GameObject go, Vector3 position, Vector3 euler, Vector3 scale, bool active)
		{
			//IL_0023: 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_002b: 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_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (LayoutSkip.IsAirportPickup(path) || LayoutSkip.IsAirportPickup(go))
			{
				SavedPickup item = new SavedPickup
				{
					path = path,
					position = position,
					euler = euler,
					scale = scale,
					active = active
				};
				Saved.Add(item);
				HoldPhysics(go);
			}
		}

		internal static void Reapply()
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			for (int i = 0; i < Saved.Count; i++)
			{
				SavedPickup savedPickup = Saved[i];
				GameObject val = AirportLayoutLoader.FindSceneObject(savedPickup.path);
				if ((Object)(object)val == (Object)null)
				{
					val = GameObject.Find(savedPickup.path);
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource logger = AirportRemixedPlugin.Logger;
					if (logger != null)
					{
						logger.LogWarning((object)("Pickup still missing after load: " + savedPickup.path));
					}
				}
				else
				{
					val.transform.localPosition = savedPickup.position;
					val.transform.localEulerAngles = savedPickup.euler;
					val.transform.localScale = savedPickup.scale;
					val.transform.hasChanged = true;
					val.SetActive(savedPickup.active);
					HoldPhysics(val);
					num++;
				}
			}
			if (num > 0)
			{
				ManualLogSource logger2 = AirportRemixedPlugin.Logger;
				if (logger2 != null)
				{
					logger2.LogInfo((object)("Reapplied " + num + " moved airport pickup(s)."));
				}
			}
		}

		private static void HoldPhysics(GameObject go)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null)
			{
				return;
			}
			Rigidbody[] componentsInChildren = go.GetComponentsInChildren<Rigidbody>(true);
			foreach (Rigidbody val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					val.isKinematic = true;
					val.linearVelocity = Vector3.zero;
					val.angularVelocity = Vector3.zero;
				}
			}
		}
	}
	internal static class AirportBehaviorBinder
	{
		private static readonly HashSet<string> UnknownKinds = new HashSet<string>();

		public static void ApplySaved()
		{
			Apply(TryLoad(out var json), json);
		}

		public static void Apply(AirportLayoutFile layout)
		{
			Apply(layout, null);
		}

		public static void Apply(AirportLayoutFile layout, string rawJson)
		{
			AirportMoveRuntime.Clear();
			int num = 0;
			int num2 = 0;
			bool flag = AirportLayoutLoader.IsAirportEditorLoaded() && ShouldUseJsonFunctions(layout, rawJson);
			if (flag)
			{
				for (int i = 0; i < layout.functions.Length; i++)
				{
					if (AirportMoveRuntime.Bind(layout.functions[i]))
					{
						num++;
					}
					else
					{
						num2++;
					}
				}
			}
			else
			{
				num += BakedAirportFunctions.Bind();
			}
			AirportMoveRuntime.FinishBind();
			LayoutBehavior[] array = layout?.behaviors;
			if (array != null)
			{
				foreach (LayoutBehavior layoutBehavior in array)
				{
					if (layoutBehavior == null || !layoutBehavior.enabled)
					{
						continue;
					}
					if (string.IsNullOrEmpty(layoutBehavior.kind))
					{
						num2++;
						continue;
					}
					if (string.Equals(layoutBehavior.kind, "move", StringComparison.OrdinalIgnoreCase))
					{
						if (AirportMoveRuntime.BindLegacyMove(layoutBehavior))
						{
							num++;
						}
						else
						{
							num2++;
						}
						continue;
					}
					if (!UnknownKinds.Contains(layoutBehavior.kind))
					{
						UnknownKinds.Add(layoutBehavior.kind);
						ManualLogSource logger = AirportRemixedPlugin.Logger;
						if (logger != null)
						{
							logger.LogWarning((object)("Airport Remixed has no handler yet for behavior kind '" + layoutBehavior.kind + "'. Target: " + layoutBehavior.target + ". The scene still loaded."));
						}
					}
					num2++;
				}
			}
			ManualLogSource logger2 = AirportRemixedPlugin.Logger;
			if (logger2 != null)
			{
				logger2.LogInfo((object)("Airport layout behaviors: " + num + " bound, " + num2 + " skipped" + (flag ? (" (" + layout.functions.Length + " functions from editor JSON).") : " (last editor bake).")));
			}
			if (num == 0)
			{
				ManualLogSource logger3 = AirportRemixedPlugin.Logger;
				if (logger3 != null)
				{
					logger3.LogWarning((object)"No airport functions bound — nothing was saved in the editor function list.");
				}
			}
		}

		private static bool ShouldUseJsonFunctions(AirportLayoutFile layout, string rawJson)
		{
			if (layout == null || layout.functions == null)
			{
				return false;
			}
			if (layout.functions.Length != 0)
			{
				return true;
			}
			return LooksLikeEmptyFunctionsArray(rawJson);
		}

		private static bool LooksLikeEmptyFunctionsArray(string json)
		{
			if (string.IsNullOrEmpty(json))
			{
				return false;
			}
			int num = json.IndexOf("\"functions\"", StringComparison.Ordinal);
			if (num < 0)
			{
				return false;
			}
			int num2 = json.IndexOf('[', num);
			if (num2 < 0)
			{
				return false;
			}
			for (int i = num2 + 1; i < json.Length; i++)
			{
				char c = json[i];
				if (c != ' ' && c != '\n' && c != '\r' && c != '\t')
				{
					return c == ']';
				}
			}
			return false;
		}

		private static void CountNested(AirportLayoutFile file, out int buttons, out int poses)
		{
			buttons = 0;
			poses = 0;
			if (file == null || file.functions == null)
			{
				return;
			}
			for (int i = 0; i < file.functions.Length; i++)
			{
				LayoutFunction layoutFunction = file.functions[i];
				if (layoutFunction == null)
				{
					continue;
				}
				if (layoutFunction.buttons != null)
				{
					buttons += layoutFunction.buttons.Length;
				}
				AddPoses(layoutFunction.steps, ref poses);
				if (layoutFunction.states == null)
				{
					continue;
				}
				for (int j = 0; j < layoutFunction.states.Length; j++)
				{
					if (layoutFunction.states[j] != null)
					{
						AddPoses(layoutFunction.states[j].steps, ref poses);
					}
				}
				if (layoutFunction.buttons == null)
				{
					continue;
				}
				for (int k = 0; k < layoutFunction.buttons.Length; k++)
				{
					if (layoutFunction.buttons[k] != null)
					{
						AddPoses(layoutFunction.buttons[k].steps, ref poses);
					}
				}
			}
		}

		private static void AddPoses(LayoutStep[] steps, ref int poses)
		{
			if (steps == null)
			{
				return;
			}
			for (int i = 0; i < steps.Length; i++)
			{
				if (steps[i] != null && steps[i].poses != null)
				{
					poses += steps[i].poses.Length;
				}
			}
		}

		private static AirportLayoutFile TryLoad(out string json)
		{
			json = null;
			try
			{
				json = AirportLayoutLoader.LoadLayoutJsonForBehaviors();
				if (string.IsNullOrEmpty(json))
				{
					return null;
				}
				AirportLayoutFile airportLayoutFile = AirportLayoutFile.Parse(json);
				int num = ((airportLayoutFile != null && airportLayoutFile.functions != null) ? airportLayoutFile.functions.Length : 0);
				int buttons = 0;
				int poses = 0;
				CountNested(airportLayoutFile, out buttons, out poses);
				ManualLogSource logger = AirportRemixedPlugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)("Parsed airport functions JSON: " + num + " function(s), " + buttons + " menu button(s), " + poses + " pose(s), " + ((json != null) ? json.Length : 0) + " chars after strip."));
				}
				return airportLayoutFile;
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = AirportRemixedPlugin.Logger;
				if (logger2 != null)
				{
					logger2.LogWarning((object)("Could not load layout behaviors: " + ex.Message));
				}
				return null;
			}
		}
	}
	internal static class AirportMoveRuntime
	{
		private sealed class AutoWait
		{
			public string id;

			public float wait;

			public LayoutFunction fn;
		}

		private sealed class MoveTrack
		{
			public GameObject go;

			public Vector3 fromPos;

			public Quaternion fromRot;

			public Vector3 toPos;

			public Quaternion toRot;

			public float speed;

			public bool easeIn;

			public bool easeOut;

			public bool curve;

			public bool facePath;

			public bool useTurn;

			public float tilt;

			public float bend;

			public Quaternion pathFromRot;

			public float t;
		}

		private sealed class SeqJob
		{
			public string id;

			public LayoutStep[] steps;

			public bool random;

			public bool advanceState;

			public bool fromLocal;

			public bool uninterruptible;

			public bool loop;

			public int wraps;

			public readonly List<int> lockIds = new List<int>();

			public GameObject fallback;

			public int step;

			public readonly List<MoveTrack> moves = new List<MoveTrack>();

			public float wait;
		}

		internal const byte EventCode = 187;

		internal const string Magic = "tony4twentys.Airport_Remixed";

		private static readonly List<LayoutFunction> Functions = new List<LayoutFunction>();

		private static readonly Dictionary<GameObject, AirportFnPrompt> Prompts = new Dictionary<GameObject, AirportFnPrompt>();

		private static readonly List<SeqJob> Jobs = new List<SeqJob>();

		private static readonly Dictionary<string, int> PoseCursor = new Dictionary<string, int>();

		private static readonly Dictionary<string, int> StateCursor = new Dictionary<string, int>();

		private static readonly List<AutoWait> Autos = new List<AutoWait>();

		private static readonly List<GameObject> TargetScratch = new List<GameObject>(8);

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

		private static readonly HashSet<string> StartedBackground = new HashSet<string>();

		private static readonly HashSet<string> WarnedEmptyLoop = new HashSet<string>();

		private static readonly Dictionary<int, Vector3> LoopPos = new Dictionary<int, Vector3>(8);

		private static readonly Dictionary<int, Quaternion> LoopRot = new Dictionary<int, Quaternion>(8);

		private static AirportMoveNet _net;

		public static int PromptCount => Prompts.Count;

		public static bool Bind(LayoutFunction function)
		{
			if (function == null || !function.enabled)
			{
				return false;
			}
			AirportAnimPlayback.Normalize(function);
			Functions.Add(function);
			EnsureNet();
			return true;
		}

		public static bool BindLegacyMove(LayoutBehavior behavior)
		{
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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)
			if (behavior == null)
			{
				return false;
			}
			return Bind(new LayoutFunction
			{
				id = behavior.id,
				kind = "trigger",
				triggerKind = "prompt",
				target = behavior.target,
				targetId = behavior.targetId,
				prompt = (string.IsNullOrEmpty(behavior.text) ? "Open" : behavior.text),
				action = "move",
				end = behavior.end,
				endEuler = behavior.endEuler,
				hasEnd = true,
				speed = ((behavior.number <= 0f) ? 1f : behavior.number)
			});
		}

		public static void FinishBind()
		{
			RebuildPrompts();
			ArmBackground();
		}

		public static void NotifySceneReady()
		{
			ArmBackground();
		}

		public static void Tick()
		{
			AirportAnimMenu.Tick();
			foreach (KeyValuePair<GameObject, AirportFnPrompt> prompt in Prompts)
			{
				if (prompt.Value != null)
				{
					prompt.Value.Follow();
				}
			}
			for (int num = Jobs.Count - 1; num >= 0; num--)
			{
				if (!StepJob(Jobs[num]))
				{
					SeqJob seqJob = Jobs[num];
					Jobs.RemoveAt(num);
					if (seqJob != null && seqJob.advanceState)
					{
						ArmAutoAfter(seqJob.id);
					}
				}
			}
			for (int num2 = Autos.Count - 1; num2 >= 0; num2--)
			{
				Autos[num2].wait -= Time.deltaTime;
				if (!(Autos[num2].wait > 0f))
				{
					LayoutFunction fn = Autos[num2].fn;
					Autos.RemoveAt(num2);
					RunFunction(fn, broadcast: true);
				}
			}
			if (AirportFunctionLoop.RoomChanged())
			{
				if (AirportFunctionLoop.HasEpoch)
				{
					ReseekLoops();
				}
				else
				{
					BroadcastLoopRequest();
				}
			}
			ArmBackground();
		}

		internal static string PromptOf(LayoutFunction fn)
		{
			LayoutFnState layoutFnState = AirportAnimPlayback.StateAt(fn, StateIndex(fn));
			if (layoutFnState != null)
			{
				return Sanitize(layoutFnState.prompt, "Open");
			}
			return Sanitize(fn?.prompt, "Open");
		}

		internal static string TitleOf(LayoutFunction fn)
		{
			LayoutFnState layoutFnState = AirportAnimPlayback.StateAt(fn, StateIndex(fn));
			string text = ((layoutFnState != null) ? layoutFnState.title : fn?.title);
			if (!string.IsNullOrEmpty(text))
			{
				return text.Trim();
			}
			return PromptOf(fn);
		}

		public static void Clear()
		{
			AirportAnimMenu.Close();
			foreach (KeyValuePair<GameObject, AirportFnPrompt> prompt in Prompts)
			{
				if (prompt.Value != null)
				{
					prompt.Value.Teardown();
				}
			}
			Prompts.Clear();
			AirportFnContact[] array = Object.FindObjectsByType<AirportFnContact>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			for (int i = 0; i < array.Length; i++)
			{
				if ((Object)(object)array[i] != (Object)null)
				{
					Object.Destroy((Object)(object)array[i]);
				}
			}
			Functions.Clear();
			Jobs.Clear();
			PoseCursor.Clear();
			StateCursor.Clear();
			Autos.Clear();
			StartedBackground.Clear();
			WarnedEmptyLoop.Clear();
			AirportFunctionLoop.ClearAll();
		}

		internal static void RunButton(string buttonId, bool fromLocal)
		{
			if (string.IsNullOrEmpty(buttonId))
			{
				return;
			}
			LayoutFunction menu;
			LayoutMenuButton layoutMenuButton = FindMenuButton(buttonId, out menu);
			if (fromLocal)
			{
				AirportAnimMenu.Close();
				if (AirportAnimPlayback.ButtonHasWorldEffect(layoutMenuButton) || HasButtonListeners(buttonId))
				{
					Broadcast("button", buttonId);
				}
			}
			if (layoutMenuButton != null)
			{
				if (layoutMenuButton.action == "openMenu")
				{
					if (fromLocal)
					{
						OpenMenu(layoutMenuButton.actionMenuId);
					}
				}
				else
				{
					StartSteps(layoutMenuButton.id, layoutMenuButton.steps, menu?.random ?? false, FindTarget(layoutMenuButton.target, layoutMenuButton.targetId) ?? ((menu != null) ? FindTarget(menu.target, menu.targetId) : null), advanceState: false, fromLocal);
					if (layoutMenuButton.steps == null || layoutMenuButton.steps.Length == 0)
					{
						LayoutFunction layoutFunction = FindFunctionById(layoutMenuButton.actionMenuId) ?? FindPhotoboothMenuFunction(layoutMenuButton);
						if (layoutFunction != null)
						{
							RunFunction(layoutFunction, fromLocal);
						}
					}
				}
			}
			for (int i = 0; i < Functions.Count; i++)
			{
				LayoutFunction layoutFunction2 = Functions[i];
				if (layoutFunction2 != null && string.Equals(layoutFunction2.kind, "trigger", StringComparison.OrdinalIgnoreCase) && string.Equals(layoutFunction2.triggerKind, "button", StringComparison.OrdinalIgnoreCase) && string.Equals(layoutFunction2.listenButtonId, buttonId, StringComparison.Ordinal))
				{
					RunFunction(layoutFunction2, broadcast: false);
				}
			}
		}

		private static LayoutMenuButton FindMenuButton(string buttonId, out LayoutFunction menu)
		{
			menu = null;
			if (string.IsNullOrEmpty(buttonId))
			{
				return null;
			}
			for (int i = 0; i < Functions.Count; i++)
			{
				LayoutFunction layoutFunction = Functions[i];
				if (layoutFunction == null || layoutFunction.buttons == null || !string.Equals(layoutFunction.kind, "menu", StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				for (int j = 0; j < layoutFunction.buttons.Length; j++)
				{
					LayoutMenuButton layoutMenuButton = layoutFunction.buttons[j];
					if (layoutMenuButton != null && string.Equals(layoutMenuButton.id, buttonId, StringComparison.Ordinal))
					{
						menu = layoutFunction;
						return layoutMenuButton;
					}
				}
			}
			return null;
		}

		private static bool HasButtonListeners(string buttonId)
		{
			if (string.IsNullOrEmpty(buttonId))
			{
				return false;
			}
			for (int i = 0; i < Functions.Count; i++)
			{
				LayoutFunction layoutFunction = Functions[i];
				if (layoutFunction != null && string.Equals(layoutFunction.kind, "trigger", StringComparison.OrdinalIgnoreCase) && string.Equals(layoutFunction.triggerKind, "button", StringComparison.OrdinalIgnoreCase) && string.Equals(layoutFunction.listenButtonId, buttonId, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		internal static void RunFunction(LayoutFunction fn, bool broadcast)
		{
			if (fn == null || FunctionBlocked(fn))
			{
				return;
			}
			if (fn.action == "openMenu")
			{
				if (broadcast)
				{
					PlayFunction(fn, fromLocal: true);
				}
				return;
			}
			if (broadcast && AirportAnimPlayback.FunctionHasWorldEffect(fn))
			{
				Broadcast("seq", fn.id);
			}
			PlayFunction(fn, broadcast);
		}

		private static void PlayFunction(LayoutFunction fn, bool fromLocal)
		{
			if (fn == null)
			{
				return;
			}
			if (fn.action == "openMenu")
			{
				if (fromLocal)
				{
					OpenMenu(fn.actionMenuId);
				}
				return;
			}
			if (fn.action == "runFn" && !AirportAnimPlayback.HasPlayableSteps(fn))
			{
				PlayFunction(FindFunctionById(fn.actionMenuId), fromLocal);
				return;
			}
			CancelAuto(fn.id);
			int num = StateIndex(fn);
			LayoutFnState layoutFnState = AirportAnimPlayback.StateAt(fn, num);
			LayoutStep[] steps = ((layoutFnState != null && layoutFnState.steps != null) ? layoutFnState.steps : fn.steps);
			GameObject fallback = FindTarget(fn.target, fn.targetId);
			FillLockIds(steps, fallback, IncomingLock);
			if (!BlockedByRunning(fn.id, IncomingLock))
			{
				bool flag = string.Equals(fn.kind, "trigger", StringComparison.OrdinalIgnoreCase);
				if (flag && AirportAnimPlayback.StateCount(fn) > 0)
				{
					StateCursor[fn.id] = AirportAnimPlayback.NextStateIndex(fn, num);
					RefreshPrompt();
				}
				StartSteps(fn.id, steps, fn.random, fallback, flag, fromLocal);
			}
		}

		private static LayoutFunction FindFunctionById(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return null;
			}
			if (string.Equals(id, "fn-38920e94", StringComparison.Ordinal))
			{
				id = "fn-a322b4e5";
			}
			for (int i = 0; i < Functions.Count; i++)
			{
				if (Functions[i] != null && string.Equals(Functions[i].id, id, StringComparison.Ordinal))
				{
					return Functions[i];
				}
			}
			return null;
		}

		private static LayoutFunction FindPhotoboothMenuFunction(LayoutMenuButton button)
		{
			if (button == null)
			{
				return null;
			}
			if (string.Equals(button.id, "btn-078ba4e2", StringComparison.Ordinal))
			{
				return FindFunctionById("fn-5b4b2393");
			}
			if (string.Equals(button.id, "btn-18ab9384", StringComparison.Ordinal))
			{
				return FindFunctionById("fn-eaeacc6c");
			}
			if (string.Equals(button.id, "btn-014d5437", StringComparison.Ordinal))
			{
				return FindFunctionById("fn-1457e09e");
			}
			return null;
		}

		internal static void RefreshPrompt()
		{
			GUIManager instance = GUIManager.instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.RefreshInteractablePrompt();
			}
		}

		internal static void RunFunction(LayoutFunction fn)
		{
			RunFunction(fn, broadcast: true);
		}

		internal static void OpenMenu(string menuId)
		{
			for (int i = 0; i < Functions.Count; i++)
			{
				LayoutFunction layoutFunction = Functions[i];
				if (layoutFunction != null && string.Equals(layoutFunction.kind, "menu", StringComparison.OrdinalIgnoreCase) && string.Equals(layoutFunction.id, menuId, StringComparison.Ordinal))
				{
					AirportAnimMenu.Open(layoutFunction);
					break;
				}
			}
		}

		internal static void RunSeqId(string id)
		{
			RunSeqIdLocal(id, fromLocal: false);
		}

		private static void RunSeqIdLocal(string id, bool fromLocal)
		{
			PlayFunction(FindFunctionById(id), fromLocal);
		}

		internal static string Sanitize(string text, string fallback)
		{
			if (string.IsNullOrEmpty(text))
			{
				return fallback;
			}
			text = text.Trim();
			if (text.Length != 0)
			{
				return text;
			}
			return fallback;
		}

		private static void ArmBackground()
		{
			if (!AirportFunctionLoop.CanRun())
			{
				return;
			}
			EnsureNet();
			if (AirportFunctionLoop.WaitForHostClock())
			{
				return;
			}
			AirportFunctionLoop.EnsureEpoch();
			for (int i = 0; i < Functions.Count; i++)
			{
				LayoutFunction layoutFunction = Functions[i];
				if (layoutFunction != null && string.Equals(layoutFunction.kind, "trigger", StringComparison.OrdinalIgnoreCase) && !HasJob(layoutFunction.id))
				{
					if (AirportFunctionLoop.IsLoop(layoutFunction))
					{
						StartLoopJob(layoutFunction);
					}
					else if (string.Equals(layoutFunction.triggerKind, "auto", StringComparison.OrdinalIgnoreCase) && !StartedBackground.Contains(layoutFunction.id ?? string.Empty))
					{
						StartedBackground.Add(layoutFunction.id ?? string.Empty);
						StartSteps(layoutFunction.id, layoutFunction.steps, layoutFunction.random, FindTarget(layoutFunction.target, layoutFunction.targetId), advanceState: false, fromLocal: false);
					}
				}
			}
		}

		internal static void BroadcastLoopClock()
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (PhotonNetwork.InRoom && AirportFunctionLoop.HasEpoch)
				{
					object[] array = new object[4]
					{
						"tony4twentys.Airport_Remixed",
						"loopclk",
						string.Empty,
						AirportFunctionLoop.Epoch
					};
					RaiseEventOptions val = new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)0
					};
					PhotonNetwork.RaiseEvent((byte)187, (object)array, val, SendOptions.SendReliable);
				}
			}
			catch
			{
			}
		}

		internal static void BroadcastLoopRequest()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (PhotonNetwork.InRoom)
				{
					object[] array = new object[3]
					{
						"tony4twentys.Airport_Remixed",
						"loopreq",
						string.Empty
					};
					RaiseEventOptions val = new RaiseEventOptions
					{
						Receivers = (ReceiverGroup)2
					};
					PhotonNetwork.RaiseEvent((byte)187, (object)array, val, SendOptions.SendReliable);
				}
			}
			catch
			{
			}
		}

		internal static void ApplyLoopClock(double epoch)
		{
			AirportFunctionLoop.SetEpoch(epoch);
			ReseekLoops();
		}

		private static void ReseekLoops()
		{
			for (int num = Jobs.Count - 1; num >= 0; num--)
			{
				if (Jobs[num] != null && Jobs[num].loop)
				{
					Jobs.RemoveAt(num);
				}
			}
			ArmBackground();
		}

		private static bool HasJob(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return false;
			}
			for (int i = 0; i < Jobs.Count; i++)
			{
				if (Jobs[i] != null && string.Equals(Jobs[i].id, id, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static void StartLoopJob(LayoutFunction fn)
		{
			if (fn == null || HasJob(fn.id))
			{
				return;
			}
			LayoutStep[] steps = fn.steps;
			if (steps == null || steps.Length == 0)
			{
				return;
			}
			GameObject fallback = FindTarget(fn.target, fn.targetId);
			CaptureLoopTargets(steps, fallback);
			float num = LoopCycleSeconds(steps, fallback);
			if (num < 0.05f)
			{
				string text = fn.id ?? string.Empty;
				if (WarnedEmptyLoop.Add(text))
				{
					ManualLogSource logger = AirportRemixedPlugin.Logger;
					if (logger != null)
					{
						logger.LogWarning((object)("Loop '" + text + "' has no move/wait time, so it was not started."));
					}
				}
				return;
			}
			SeqJob seqJob = new SeqJob();
			seqJob.id = fn.id ?? string.Empty;
			seqJob.steps = steps;
			seqJob.random = false;
			seqJob.fallback = fallback;
			seqJob.loop = true;
			float num2 = AirportFunctionLoop.Phase(num);
			if (num2 > 0.001f && SeekLoop(seqJob, num2))
			{
				Jobs.Add(seqJob);
				return;
			}
			seqJob.step = 0;
			if (BeginStep(seqJob))
			{
				Jobs.Add(seqJob);
			}
		}

		private static void CaptureLoopTargets(LayoutStep[] steps, GameObject fallback)
		{
			AirportFunctionLoop.Capture(fallback);
			if (steps == null)
			{
				return;
			}
			foreach (LayoutStep layoutStep in steps)
			{
				if (layoutStep == null)
				{
					continue;
				}
				AirportFunctionLoop.Capture(FindTarget(layoutStep.animTarget, layoutStep.animTargetId));
				if (layoutStep.poses == null)
				{
					continue;
				}
				for (int j = 0; j < layoutStep.poses.Length; j++)
				{
					if (layoutStep.poses[j] != null)
					{
						AirportFunctionLoop.Capture(FindTarget(layoutStep.poses[j].target, layoutStep.poses[j].targetId));
					}
				}
			}
		}

		private static float LoopCycleSeconds(LayoutStep[] steps, GameObject fallback)
		{
			LoopPos.Clear();
			LoopRot.Clear();
			SeedLoopPose(fallback);
			if (steps == null)
			{
				return 0f;
			}
			float num = 0f;
			int num2 = 0;
			while (num2 < steps.Length)
			{
				int num3 = AirportAnimPlayback.GroupEnd(steps, num2);
				float num4 = 0f;
				for (int i = num2; i <= num3; i++)
				{
					num4 = Mathf.Max(num4, StepLoopSeconds(steps[i], fallback));
				}
				for (int j = num2; j <= num3; j++)
				{
					CommitLoopPose(steps[j], fallback);
				}
				num += num4;
				num2 = num3 + 1;
			}
			return num;
		}

		private static bool SeekLoop(SeqJob job, float phase)
		{
			LoopPos.Clear();
			LoopRot.Clear();
			SeedLoopPose(job.fallback);
			float num = 0f;
			int num2 = 0;
			while (num2 < job.steps.Length)
			{
				int num3 = AirportAnimPlayback.GroupEnd(job.steps, num2);
				float num4 = 0f;
				for (int i = num2; i <= num3; i++)
				{
					num4 = Mathf.Max(num4, StepLoopSeconds(job.steps[i], job.fallback));
				}
				if (phase <= num + num4 || num3 == job.steps.Length - 1)
				{
					float num5 = Mathf.Max(0f, phase - num);
					job.moves.Clear();
					job.wait = 0f;
					job.step = num3;
					for (int j = num2; j <= num3; j++)
					{
						SeekOne(job, job.steps[j], j, (num4 > 0f) ? Mathf.Clamp01(num5 / num4) : 1f);
					}
					if (job.moves.Count <= 0 && !(job.wait > 0f))
					{
						return BeginStepAfterSeek(job);
					}
					return true;
				}
				for (int k = num2; k <= num3; k++)
				{
					SnapLoopStep(job.steps[k], job.fallback);
					CommitLoopPose(job.steps[k], job.fallback);
				}
				num += num4;
				num2 = num3 + 1;
			}
			return false;
		}

		private static bool BeginStepAfterSeek(SeqJob job)
		{
			if (job.moves.Count > 0 || job.wait > 0f)
			{
				return true;
			}
			job.step++;
			if (job.step < job.steps.Length)
			{
				return BeginStep(job);
			}
			job.step = 0;
			return BeginStep(job);
		}

		private static void SeedLoopPose(GameObject go)
		{
			//IL_0042: 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_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)go == (Object)null))
			{
				int instanceID = ((Object)go).GetInstanceID();
				if (AirportFunctionLoop.TryRest(go, out var pos, out var rot))
				{
					LoopPos[instanceID] = pos;
					LoopRot[instanceID] = rot;
				}
				else
				{
					LoopPos[instanceID] = go.transform.position;
					LoopRot[instanceID] = go.transform.rotation;
				}
			}
		}

		private static GameObject StepLoopTarget(LayoutStep step, GameObject fallback)
		{
			if (step == null)
			{
				return fallback;
			}
			if (step.poses != null && step.poses.Length != 0 && step.poses[0] != null)
			{
				GameObject val = FindTarget(step.poses[0].target, step.poses[0].targetId);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			GameObject val2 = FindTarget(step.animTarget, step.animTargetId);
			if (!((Object)(object)val2 != (Object)null))
			{
				return fallback;
			}
			return val2;
		}

		private static float StepLoopSeconds(LayoutStep step, GameObject fallback)
		{
			//IL_00a8: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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)
			if (step == null)
			{
				return 0f;
			}
			string text = step.kind ?? "move";
			if (text == "delay")
			{
				return Mathf.Clamp(step.delay, 0f, 30f);
			}
			if (AirportAnimPlayback.IsAnimKind(text))
			{
				return 0.5f;
			}
			if (text != "move")
			{
				return 0f;
			}
			if (step.poses == null || step.poses.Length == 0 || step.poses[0] == null)
			{
				return 0f;
			}
			GameObject val = StepLoopTarget(step, fallback);
			if ((Object)(object)val == (Object)null)
			{
				return 0f;
			}
			SeedLoopPose(val);
			int instanceID = ((Object)val).GetInstanceID();
			return AirportAnimPlayback.MoveDuration(LoopPos[instanceID], step.poses[0].position, LoopRot[instanceID], Quaternion.Euler(step.poses[0].euler), step.speed);
		}

		private static void CommitLoopPose(LayoutStep step, GameObject fallback)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (step != null && !(step.kind != "move") && step.poses != null && step.poses.Length != 0 && step.poses[0] != null)
			{
				GameObject val = StepLoopTarget(step, fallback);
				if (!((Object)(object)val == (Object)null))
				{
					int instanceID = ((Object)val).GetInstanceID();
					LoopPos[instanceID] = step.poses[0].position;
					LoopRot[instanceID] = Quaternion.Euler(step.poses[0].euler);
				}
			}
		}

		private static void SnapLoopStep(LayoutStep step, GameObject fallback)
		{
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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)
			if (step == null)
			{
				return;
			}
			string text = step.kind ?? "move";
			GameObject val = StepLoopTarget(step, fallback);
			if (AirportAnimPlayback.IsToggleKind(text) && (Object)(object)val != (Object)null)
			{
				AirportAnimPlayback.ApplyToggle(val, step.flag);
			}
			else if (AirportAnimPlayback.IsMaterialKind(text) && (Object)(object)val != (Object)null)
			{
				string text2 = AirportAnimPlayback.MaterialName(step);
				if (!string.IsNullOrEmpty(text2))
				{
					LayoutMaterials.Apply(val, text2);
				}
			}
			else if (text == "move" && (Object)(object)val != (Object)null && step.poses != null && step.poses.Length != 0 && step.poses[0] != null)
			{
				val.transform.position = step.poses[0].position;
				val.transform.rotation = Quaternion.Euler(step.poses[0].euler);
			}
		}

		private static void SeekOne(SeqJob job, LayoutStep step, int index, float u)
		{
			//IL_00aa: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: 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_00f9: 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_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: 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_017a: 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)
			if (job == null || step == null)
			{
				return;
			}
			string text = step.kind ?? "move";
			if (text == "delay")
			{
				float num = Mathf.Clamp(step.delay, 0f, 30f);
				job.wait = Mathf.Max(job.wait, num * (1f - u));
			}
			else if (!(text != "move") && step.poses != null && step.poses.Length != 0 && step.poses[0] != null)
			{
				GameObject val = StepLoopTarget(step, job.fallback);
				if (!((Object)(object)val == (Object)null))
				{
					SeedLoopPose(val);
					int instanceID = ((Object)val).GetInstanceID();
					Vector3 fromPos = LoopPos[instanceID];
					Quaternion fromRot = LoopRot[instanceID];
					Vector3 position = step.poses[0].position;
					Quaternion toRot = Quaternion.Euler(step.poses[0].euler);
					MoveTrack moveTrack = new MoveTrack();
					moveTrack.go = val;
					moveTrack.fromPos = fromPos;
					moveTrack.fromRot = fromRot;
					moveTrack.toPos = position;
					moveTrack.toRot = toRot;
					moveTrack.speed = step.speed;
					moveTrack.easeIn = step.easeIn;
					moveTrack.easeOut = step.easeOut;
					moveTrack.t = u;
					BindCurveAuthored(moveTrack, job, val, index);
					FillPath(moveTrack, step);
					float u2 = AirportAnimPlayback.Ease01(u, step.easeIn, step.easeOut);
					EvalMove(moveTrack, u2, out var pos, out var rot);
					val.transform.position = pos;
					val.transform.rotation = rot;
					job.moves.Add(moveTrack);
				}
			}
		}

		private static void StartSteps(string id, LayoutStep[] steps, bool random, GameObject fallback, bool advanceState, bool fromLocal)
		{
			if (steps == null || steps.Length == 0)
			{
				return;
			}
			FillLockIds(steps, fallback, IncomingLock);
			if (BlockedByRunning(id, IncomingLock))
			{
				return;
			}
			for (int num = Jobs.Count - 1; num >= 0; num--)
			{
				if (Jobs[num] != null && string.Equals(Jobs[num].id, id, StringComparison.Ordinal))
				{
					Jobs.RemoveAt(num);
				}
			}
			SeqJob seqJob = new SeqJob();
			seqJob.id = id ?? string.Empty;
			seqJob.steps = steps;
			seqJob.random = random;
			seqJob.fallback = fallback;
			seqJob.advanceState = advanceState;
			seqJob.fromLocal = fromLocal;
			seqJob.uninterruptible = AirportAnimPlayback.AnyUninterruptible(steps);
			if (seqJob.uninterruptible)
			{
				for (int i = 0; i < IncomingLock.Count; i++)
				{
					seqJob.lockIds.Add(IncomingLock[i]);
				}
			}
			seqJob.step = 0;
			if (BeginStep(seqJob))
			{
				Jobs.Add(seqJob);
			}
		}

		private static bool FunctionBlocked(LayoutFunction fn)
		{
			if (fn == null)
			{
				return false;
			}
			int index = StateIndex(fn);
			LayoutFnState layoutFnState = AirportAnimPlayback.StateAt(fn, index);
			FillLockIds((layoutFnState != null && layoutFnState.steps != null) ? layoutFnState.steps : fn.steps, FindTarget(fn.target, fn.targetId), IncomingLock);
			return BlockedByRunning(fn.id, IncomingLock);
		}

		private static bool BlockedByRunning(string id, List<int> incoming)
		{
			for (int i = 0; i < Jobs.Count; i++)
			{
				SeqJob seqJob = Jobs[i];
				if (seqJob != null && seqJob.uninterruptible)
				{
					if (!string.IsNullOrEmpty(id) && string.Equals(seqJob.id, id, StringComparison.Ordinal))
					{
						return true;
					}
					if (LocksOverlap(seqJob.lockIds, incoming))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool LocksOverlap(List<int> a, List<int> b)
		{
			if (a == null || b == null || a.Count == 0 || b.Count == 0)
			{
				return false;
			}
			for (int i = 0; i < a.Count; i++)
			{
				for (int j = 0; j < b.Count; j++)
				{
					if (a[i] == b[j])
					{
						return true;
					}
				}
			}
			return false;
		}

		private static void FillLockIds(LayoutStep[] steps, GameObject fallback, List<int> dest)
		{
			dest.Clear();
			if (steps != null)
			{
				foreach (LayoutStep layoutStep in steps)
				{
					if (layoutStep == null)
					{
						continue;
					}
					AddLock(dest, FindTarget(layoutStep.animTarget, layoutStep.animTargetId));
					if (layoutStep.poses == null)
					{
						continue;
					}
					for (int j = 0; j < layoutStep.poses.Length; j++)
					{
						if (layoutStep.poses[j] != null)
						{
							AddLock(dest, FindTarget(layoutStep.poses[j].target, layoutStep.poses[j].targetId));
						}
					}
				}
			}
			if (dest.Count == 0 && (Object)(object)fallback != (Object)null)
			{
				AddLock(dest, fallback);
			}
		}

		private static void AddLock(List<int> dest, GameObject go)
		{
			if (!((Object)(object)go == (Object)null))
			{
				int instanceID = ((Object)go).GetInstanceID();
				if (!dest.Contains(instanceID))
				{
					dest.Add(instanceID);
				}
			}
		}

		private static bool BeginStep(SeqJob job)
		{
			if (job == null || job.steps == null || job.step < 0 || job.step >= job.steps.Length)
			{
				return false;
			}
			int step = job.step;
			int num = AirportAnimPlayback.GroupEnd(job.steps, step);
			job.moves.Clear();
			job.wait = 0f;
			for (int i = step; i <= num; i++)
			{
				StartOne(job, job.steps[i], i);
			}
			if (job.moves.Count == 0 && job.wait <= 0f)
			{
				job.step = num;
				return Advance(job);
			}
			job.step = num;
			return true;
		}

		private static void StartOne(SeqJob job, LayoutStep step, int index)
		{
			//IL_00d1: 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_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			if (job == null || step == null)
			{
				return;
			}
			string text = step.kind ?? "move";
			switch (text)
			{
			case "openMenu":
				if (job.fromLocal)
				{
					OpenMenu(step.actionMenuId);
				}
				return;
			case "closeMenu":
				if (job.fromLocal)
				{
					AirportAnimMenu.CloseTarget(step.actionMenuId);
				}
				return;
			case "delay":
				job.wait = Mathf.Max(job.wait, Mathf.Clamp(step.delay, 0f, 30f));
				return;
			case "runFn":
				RunSeqIdLocal(step.actionMenuId, job.fromLocal);
				return;
			case "teleport":
				if (job.fromLocal)
				{
					LayoutPose layoutPose2 = PickPose(job, step, index);
					if (layoutPose2 != null)
					{
						AirportFnFx.Teleport(layoutPose2.position);
					}
				}
				return;
			case "afflict":
				if (job.fromLocal)
				{
					AirportFnFx.Afflict(step);
				}
				return;
			case "interact":
				if (job.fromLocal)
				{
					LayoutPose layoutPose = PickPose(job, step, index);
					AirportFnFx.Interact((layoutPose != null) ? (FindTarget(layoutPose.target, layoutPose.targetId) ?? job.fallback) : job.fallback);
				}
				return;
			case "spawn":
			{
				LayoutPose layoutPose3 = PickPose(job, step, index);
				AirportFnFx.SpawnClone((layoutPose3 != null) ? (FindTarget(layoutPose3.target, layoutPose3.targetId) ?? job.fallback) : job.fallback, layoutPose3, step);
				return;
			}
			}
			if (AirportAnimPlayback.IsAnimKind(text))
			{
				AirportAnimPlayback.PlayAction(FindTarget(step.animTarget, step.animTargetId) ?? job.fallback, text, step.clipName, out var duration);
				job.wait = Mathf.Max(job.wait, duration);
				return;
			}
			if (AirportAnimPlayback.IsToggleKind(text) || AirportAnimPlayback.IsMaterialKind(text))
			{
				ApplyFx(job, step, text);
				return;
			}
			LayoutPose layoutPose4 = PickPose(job, step, index);
			GameObject val = ((layoutPose4 != null) ? (FindTarget(layoutPose4.target, layoutPose4.targetId) ?? job.fallback) : job.fallback);
			if (!((Object)(object)val == (Object)null) && layoutPose4 != null)
			{
				MoveTrack moveTrack = new MoveTrack();
				moveTrack.go = val;
				moveTrack.fromPos = val.transform.position;
				moveTrack.fromRot = val.transform.rotation;
				moveTrack.toPos = layoutPose4.position;
				moveTrack.toRot = Quaternion.Euler(layoutPose4.euler);
				moveTrack.speed = step.speed;
				moveTrack.easeIn = step.easeIn;
				moveTrack.easeOut = step.easeOut;
				moveTrack.t = 0f;
				BindCurveAuthored(moveTrack, job, val, index);
				FillPath(moveTrack, step);
				job.moves.Add(moveTrack);
			}
		}

		private static void BindCurveAuthored(MoveTrack move, SeqJob job, GameObject target, int index)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			if (move != null)
			{
				move.useTurn = FindPrevMoveRot(job, target, index, out var rot);
				move.pathFromRot = rot;
			}
		}

		private static bool FindPrevMoveRot(SeqJob job, GameObject target, int index, out Quaternion rot)
		{
			//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_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)
			rot = Quaternion.identity;
			if (job == null || job.steps == null || (Object)(object)target == (Object)null)
			{
				return false;
			}
			for (int num = index - 1; num >= 0; num--)
			{
				LayoutStep layoutStep = job.steps[num];
				if (layoutStep != null && (layoutStep.kind == null || !(layoutStep.kind != "move")))
				{
					LayoutPose layoutPose = ((layoutStep.poses != null && layoutStep.poses.Length != 0) ? layoutStep.poses[0] : null);
					if (layoutPose != null && !((Object)(object)(FindTarget(layoutPose.target, layoutPose.targetId) ?? job.fallback) != (Object)(object)target))
					{
						rot = Quaternion.Euler(layoutPose.euler);
						return true;
					}
				}
			}
			return false;
		}

		private static void FillPath(MoveTrack move, LayoutStep step)
		{
			if (move != null && step != null)
			{
				move.curve = step.curve;
				move.facePath = step.facePath;
				move.tilt = AirportAnimPlayback.ClampTilt(step.tilt);
				move.bend = AirportAnimPlayback.ClampBend((step.bend == 0f && step.curve) ? 1f : step.bend);
			}
		}

		private static void EvalMove(MoveTrack move, float u, out Vector3 pos, out Quaternion rot)
		{
			//IL_0077: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: 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_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: 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_00ea: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			Vector3 tangent;
			if (move.curve)
			{
				Quaternion aRot = (move.useTurn ? move.pathFromRot : move.fromRot);
				pos = AirportAnimPlayback.CurvePoint(move.fromPos, move.toPos, aRot, move.toRot, move.bend, u, move.useTurn);
				tangent = AirportAnimPlayback.CurveTangent(move.fromPos, move.toPos, aRot, move.toRot, move.bend, u, move.useTurn);
			}
			else
			{
				pos = Vector3.Lerp(move.fromPos, move.toPos, u);
				tangent = move.toPos - move.fromPos;
			}
			if (!move.facePath)
			{
				rot = Quaternion.Slerp(move.fromRot, move.toRot, u);
				return;
			}
			Vector3 val = move.toPos - move.fromPos;
			Vector3 val2 = val;
			Vector3 tanEnd = val;
			if (move.curve)
			{
				Quaternion aRot2 = (move.useTurn ? move.pathFromRot : move.fromRot);
				val = AirportAnimPlayback.CurveTangent(move.fromPos, move.toPos, aRot2, move.toRot, move.bend, 0f, move.useTurn);
				val2 = AirportAnimPlayback.CurveTangent(move.fromPos, move.toPos, aRot2, move.toRot, move.bend, 0.5f, move.useTurn);
				tanEnd = AirportAnimPlayback.CurveTangent(move.fromPos, move.toPos, aRot2, move.toRot, move.bend, 1f, move.useTurn);
			}
			float bank = AirportAnimPlayback.TiltBank(val, val2, tanEnd, move.tilt, u);
			rot = AirportAnimPlayback.FaceAlong(move.fromRot, tangent, val, val2, bank);
		}

		private static void ApplyFx(SeqJob job, LayoutStep step, string kind)
		{
			List<GameObject> list = CollectTargets(job, step);
			if (AirportAnimPlayback.IsToggleKind(kind))
			{
				bool flag = step.flag;
				for (int i = 0; i < list.Count; i++)
				{
					AirportAnimPlayback.ApplyToggle(list[i], flag);
				}
				return;
			}
			string text = AirportAnimPlayback.MaterialName(step);
			if (!string.IsNullOrEmpty(text))
			{
				for (int j = 0; j < list.Count; j++)
				{
					LayoutMaterials.Apply(list[j], text);
				}
			}
		}

		private static List<GameObject> CollectTargets(SeqJob job, LayoutStep step)
		{
			TargetScratch.Clear();
			if (step != null && step.poses != null)
			{
				for (int i = 0; i < step.poses.Length; i++)
				{
					LayoutPose layoutPose = step.poses[i];
					if (layoutPose != null)
					{
						GameObject val = FindTarget(layoutPose.target, layoutPose.targetId);
						if ((Object)(object)val != (Object)null && !TargetScratch.Contains(val))
						{
							TargetScratch.Add(val);
						}
					}
				}
			}
			if (TargetScratch.Count == 0 && job != null && (Object)(object)job.fallback != (Object)null)
			{
				TargetScratch.Add(job.fallback);
			}
			return TargetScratch;
		}

		private static LayoutPose PickPose(SeqJob job, LayoutStep step, int stepIndex)
		{
			if (step == null || step.poses == null || step.poses.Length == 0)
			{
				return null;
			}
			int num;
			if (job.random || step.random)
			{
				num = Random.Range(0, step.poses.Length);
			}
			else
			{
				string key = job.id + ":" + stepIndex;
				if (!PoseCursor.TryGetValue(key, out var value))
				{
					value = 0;
				}
				num = value % step.poses.Length;
				PoseCursor[key] = num + 1;
			}
			return step.poses[num];
		}

		private static bool StepJob(SeqJob job)
		{
			//IL_003a: 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_0046: 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_00a1: 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)
			if (job == null)
			{
				return false;
			}
			job.wraps = 0;
			bool flag = true;
			for (int i = 0; i < job.moves.Count; i++)
			{
				MoveTrack moveTrack = job.moves[i];
				if (moveTrack != null && !((Object)(object)moveTrack.go == (Object)null))
				{
					float num = AirportAnimPlayback.MoveDuration(moveTrack.fromPos, moveTrack.toPos, moveTrack.fromRot, moveTrack.toRot, moveTrack.speed);
					moveTrack.t += Time.deltaTime / num;
					float u = AirportAnimPlayback.Ease01(moveTrack.t, moveTrack.easeIn, moveTrack.easeOut);
					EvalMove(moveTrack, u, out var pos, out var rot);
					moveTrack.go.transform.position = pos;
					moveTrack.go.transform.rotation = rot;
					if (moveTrack.t < 1f)
					{
						flag = false;
					}
				}
			}
			job.wait -= Time.deltaTime;
			if (!flag || job.wait > 0f)
			{
				return true;
			}
			return Advance(job);
		}

		private static bool Advance(SeqJob job)
		{
			job.step++;
			if (job.step < job.steps.Length)
			{
				return BeginStep(job);
			}
			if (job.loop)
			{
				job.wraps++;
				if (job.wraps > 1)
				{
					return false;
				}
				job.step = 0;
				job.moves.Clear();
				job.wait = 0f;
				return BeginStep(job);
			}
			return false;
		}

		private static int StateIndex(LayoutFunction fn)
		{
			if (fn == null)
			{
				return 0;
			}
			if (string.IsNullOrEmpty(fn.id) || !StateCursor.TryGetValue(fn.id, out var value))
			{
				value = fn.startState;
			}
			int num = AirportAnimPlayback.StateCount(fn);
			if (num <= 0)
			{
				return 0;
			}
			return Mathf.Clamp(value, 0, num - 1);
		}

		private static void ArmAutoAfter(string id)
		{
			LayoutFunction layoutFunction = null;
			for (int i = 0; i < Functions.Count; i++)
			{
				if (Functions[i] != null && string.Equals(Functions[i].id, id, StringComparison.Ordinal))
				{
					layoutFunction = Functions[i];
					break;
				}
			}
			if (layoutFunction != null && string.Equals(layoutFunction.kind, "trigger", StringComparison.OrdinalIgnoreCase))
			{
				LayoutFnState layoutFnState = AirportAnimPlayback.StateAt(layoutFunction, StateIndex(layoutFunction));
				if (layoutFnState != null && !(layoutFnState.autoAfter <= 0f) && (!PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient))
				{
					CancelAuto(layoutFunction.id);
					AutoWait autoWait = new AutoWait();
					autoWait.id = layoutFunction.id;
					autoWait.wait = layoutFnState.autoAfter;
					autoWait.fn = layoutFunction;
					Autos.Add(autoWait);
				}
			}
		}

		private static void CancelAuto(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return;
			}
			for (int num = Autos.Count - 1; num >= 0; num--)
			{
				if (Autos[num] != null && string.Equals(Autos[num].id, id, StringComparison.Ordinal))
				{
					Autos.RemoveAt(num);
				}
			}
		}

		private static void RebuildPrompts()
		{
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<GameObject, AirportFnPrompt> prompt in Prompts)
			{
				if (prompt.Value != null)
				{
					prompt.Value.Teardown();
				}
			}
			Prompts.Clear();
			for (int i = 0; i < Functions.Count; i++)
			{
				LayoutFunction layoutFunction = Functions[i];
				if (layoutFunction == null || !string.Equals(layoutFunction.kind, "trigger", StringComparison.OrdinalIgnoreCase) || string.Equals(layoutFunction.triggerKind, "button", StringComparison.OrdinalIgnoreCase) || string.Equals(layoutFunction.triggerKind, "auto", StringComparison.OrdinalIgnoreCase) || AirportFunctionLoop.IsLoop(layoutFunction))
				{
					continue;
				}
				GameObject val = FindTarget(layoutFunction.target, layoutFunction.targetId);
				if ((Object)(object)val == (Object)null && AirportAnimPlayback.IsArea(layoutFunction) && layoutFunction.hasEnd)
				{
					val = AirportFnContact.EnsureVolume(layoutFunction);
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource logger = AirportRemixedPlugin.Logger;
					if (logger != null)
					{
						logger.LogWarning((object)("Function '" + layoutFunction.id + "' target not found: " + layoutFunction.target + " (photobooth=" + ((Object)(object)AirportLayoutLoader.FindSceneObject("Map/Photobooth") != (Object)null) + ")"));
					}
					continue;
				}
				if (AirportAnimPlayback.IsArea(layoutFunction) || AirportAnimPlayback.IsTouch(layoutFunction))
				{
					AirportFnContact airportFnContact = val.GetComponent<AirportFnContact>();
					if ((Object)(object)airportFnContact == (Object)null)
					{
						airportFnContact = val.AddComponent<AirportFnContact>();
					}
					airportFnContact.Arm(layoutFunction, AirportAnimPlayback.IsArea(layoutFunction));
					ManualLogSource logger2 = AirportRemixedPlugin.Logger;
					if (logger2 != null)
					{
						logger2.LogInfo((object)((AirportAnimPlayback.IsArea(layoutFunction) ? "Area" : "Touch") + " trigger on '" + ((Object)val).name + "'."));
					}
					continue;
				}
				AirportFnPrompt airportFnPrompt = new AirportFnPrompt();
				airportFnPrompt.Attach(val, layoutFunction);
				Prompts[val] = airportFnPrompt;
				ManualLogSource logger3 = AirportRemixedPlugin.Logger;
				if (logger3 != null)
				{
					logger3.LogInfo((object)("Prompt on '" + ((Object)val).name + "' at " + ((object)val.transform.position/*cast due to .constrained prefix*/).ToString() + " text='" + airportFnPrompt.Text() + "'"));
				}
			}
			ManualLogSource logger4 = AirportRemixedPlugin.Logger;
			if (logger4 != null)
			{
				logger4.LogInfo((object)("Airport function prompts attached: " + Prompts.Count + "."));
			}
		}

		private static GameObject FindTarget(string path, string id)
		{
			if (!string.IsNullOrEmpty(id))
			{
				AirportRemixedPiece[] array = Object.FindObjectsByType<AirportRemixedPiece>((FindObjectsInactive)1, (FindObjectsSortMode)0);
				for (int i = 0; i < array.Length; i++)
				{
					if (!((Object)(object)array[i] == (Object)null) && string.Equals(array[i].id, id, StringComparison.Ordinal))
					{
						Transform transform = ((Component)array[i]).transform;
						if (!((Object)(object)transform != (Object)null) || !(((Object)transform).name == "Cube") || !((Object)(object)transform.parent != (Object)null) || !(((Object)transform.parent).name == "Map"))
						{
							return ((Component)array[i]).gameObject;
						}
					}
				}
			}
			GameObject val = AirportLayoutLoader.FindSceneObject(path);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			GameObject val2 = FindRemappedTarget(path);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2;
			}
			GameObject val3 = FindByExactName(path, !string.IsNullOrEmpty(id));
			if ((Object)(object)val3 != (Object)null)
			{
				return val3;
			}
			if (!string.IsNullOrEmpty(id))
			{
				return null;
			}
			GameObject val4 = FindByLeafName(path);
			if ((Object)(object)val4 != (Object)null)
			{
				return val4;
			}
			return FindPhotoboothFallback(path);
		}

		private static GameObject FindByExactName(string path, bool anyLeaf)
		{
			if (string.IsNullOrEmpty(path))
			{
				return null;
			}
			int num = path.LastIndexOf('/');
			string text = ((num < 0) ? path : path.Substring(num + 1));
			if (string.IsNullOrEmpty(text) || (!anyLeaf && !text.StartsWith("AR_", StringComparison.Ordinal)))
			{
				return null;
			}
			Transform[] array = Object.FindObjectsByType<Transform>((FindObjectsInactive)1, (FindObjectsSortMode)0);
			GameObject val = null;
			for (int i = 0; i < array.Length; i++)
			{
				if (!((Object)(object)array[i] == (Object)null))
				{
					if (((Object)array[i]).name == text)
					{
						return ((Component)array[i]).gameObject;
					}
					if ((Object)(object)val == (Object)null && AirportLayoutLoader.NamesMatchLoose(((Object)array[i]).name, text))
					{
						val = ((Component)array[i]).gameObject;
					}
				}
			}
			return val;
		}

		private static GameObject FindByLeafName(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return null;
			}
			int num = path.LastIndexOf('/');
			string text = ((num < 0) ? path : path.Substring(num + 1));
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			GameObject val = FindPhotoboothRoot();
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform[] componentsInChildren = val.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == text)
				{
					return ((Component)componentsInChildren[i]).gameObject;
				}
			}
			return null;
		}

		private static GameObject FindPhotoboothRoot()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = AirportLayoutLoader.FindSceneObject("Map/Photobooth");
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Scene activeScene = SceneManager.GetActiveScene();
			if (!((Scene)(ref activeScene)).IsValid())
			{
				return null;
			}
			GameObject[] rootGameObjects = ((Scene)(ref activeScene)).GetRootGameObjects();
			for (int i = 0; i < rootGameObjects.Length; i++)
			{
				if ((Object)(object)rootGameObjects[i] == (Object)null)
				{
					continue;
				}
				Transform[] componentsInChildren = rootGameObjects[i].GetComponentsInChildren<Transform>(true);
				for (int j = 0; j < componentsInChildren.Length; j++)
				{
					if ((Object)(object)componentsInChildren[j] != (Object)null && ((Object)componentsInChildren[j]).name == "Photobooth")
					{
						return ((Component)componentsInChildren[j]).gameObject;
					}
				}
			}
			return null;
		}

		private static GameObject FindPhotoboothFallback(string path)
		{
			if (string.IsNullOrEm