Decompiled source of CinematicPath v0.2.0

plugins\CinematicPath.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Newtonsoft.Json;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("CinematicPath")]
[assembly: AssemblyDescription("Cinematic waypoints for Valheim")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("mrGMD")]
[assembly: AssemblyProduct("CinematicPath")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.2.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.0")]
[BepInPlugin("mrGMD.cinematicpath", "CinematicPath", "0.2.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class CinematicPath : BaseUnityPlugin
{
	[HarmonyPatch(typeof(Character), "FixedUpdate")]
	private static class CharacterFixedUpdatePatch
	{
		private static bool Prefix(Character __instance)
		{
			if (Instance.isFreeCam && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Character), "UpdateGroundContact")]
	private static class CharacterUpdateGroundContactPatch
	{
		private static bool Prefix(Character __instance)
		{
			if (Instance.isFreeCam && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Character), "UpdateMotion")]
	private static class CharacterUpdateMotionPatch
	{
		private static bool Prefix(Character __instance)
		{
			if (Instance.isFreeCam && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
			{
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	private static class RigidbodySetVelocityPatch
	{
		private static bool Prefix(Rigidbody __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			if (Instance.isFreeCam && (Object)(object)__instance == (Object)(Rigidbody)bodyField.GetValue(Player.m_localPlayer))
			{
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	private static class RigidbodySetAngularVelocityPatch
	{
		private static bool Prefix(Rigidbody __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			if (Instance.isFreeCam && (Object)(object)__instance == (Object)(Rigidbody)bodyField.GetValue(Player.m_localPlayer))
			{
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Debug), "LogWarning", new Type[] { typeof(object) })]
	private static class DebugLogWarningPatch
	{
		private static bool Prefix(object message)
		{
			if (Instance.isFreeCam && message.ToString().Contains("Setting linear velocity of a kinematic body is not supported"))
			{
				return false;
			}
			return true;
		}
	}

	[HarmonyPatch(typeof(Debug), "LogWarning", new Type[]
	{
		typeof(object),
		typeof(Object)
	})]
	private static class DebugLogWarningContextPatch
	{
		private static bool Prefix(object message, Object context)
		{
			if (Instance.isFreeCam && message.ToString().Contains("Setting linear velocity of a kinematic body is not supported"))
			{
				return false;
			}
			return true;
		}
	}

	public const string PluginGUID = "mrGMD.cinematicpath";

	public const string PluginName = "CinematicPath";

	public const string PluginVersion = "0.2.2";

	public static CinematicPath Instance;

	private Dictionary<string, List<Checkpoint>> savedPaths = new Dictionary<string, List<Checkpoint>>();

	private readonly string saveFilePath = Path.Combine(Paths.ConfigPath, "mrGMD.cinematicpath.paths.json");

	private List<Checkpoint> checkpoints = new List<Checkpoint>();

	private List<Checkpoint> originals;

	private List<GameObject> markers = new List<GameObject>();

	private List<GameObject> segmentColliders = new List<GameObject>();

	private List<GameObject> labels = new List<GameObject>();

	private GameObject pathLine;

	private bool isFreeCam;

	private bool isEditMode;

	private bool isPlaying;

	private Coroutine playbackCoroutine;

	private ConfigEntry<KeyCode> toggleKey;

	private ConfigEntry<KeyCode> playKey;

	private ConfigEntry<KeyCode> clearKey;

	private ConfigEntry<float> flySpeed;

	private ConfigEntry<float> mouseSens;

	private ConfigEntry<float> defaultMoveSpeed;

	private const float defaultRotSpeed = 90f;

	private static FieldInfo hudRootField;

	private static FieldInfo visEquipmentField;

	private static FieldInfo colliderField;

	private static FieldInfo godModeField;

	private static FieldInfo maxAirAltitudeField;

	private static FieldInfo lastGroundTouchField;

	private static FieldInfo bodyField;

	private bool showAllMenu;

	private Rect allRect = new Rect(100f, 100f, 400f, 600f);

	private Vector2 scrollPos;

	private List<Checkpoint> tempCheckpoints;

	private List<EditCheckpoint> editCPs;

	private List<EditSegment> editSegs;

	private bool[] expandedCPs;

	private bool[] expandedSegs;

	private string startCpStr = "1";

	private Vector3 savedPlayerPos;

	private Quaternion savedPlayerRot;

	private bool savedGodMode;

	private bool savedKinematic;

	private Vector3 savedCamPos;

	private Quaternion savedCamRot;

	private int editingCheckpointIndex = -1;

	private bool isEditingByFreeCam;

	private string newSaveName = "";

	private Vector2 savesScrollPos;

	private bool hasChanges;

	private void Awake()
	{
		Instance = this;
		Harmony.CreateAndPatchAll(typeof(CinematicPath), (string)null);
		hudRootField = AccessTools.Field(typeof(Hud), "m_hudRoot");
		visEquipmentField = AccessTools.Field(typeof(Player), "m_visEquipment");
		colliderField = AccessTools.Field(typeof(Character), "m_collider");
		godModeField = AccessTools.Field(typeof(Player), "m_godMode");
		maxAirAltitudeField = AccessTools.Field(typeof(Character), "m_maxAirAltitude");
		lastGroundTouchField = AccessTools.Field(typeof(Character), "m_lastGroundTouch");
		bodyField = AccessTools.Field(typeof(Character), "m_body");
		toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleFreeCam", (KeyCode)291, "Toggle free cam");
		playKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "Play", (KeyCode)292, "Play/stop path");
		clearKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "Clear", (KeyCode)290, "Clear all");
		flySpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "FlySpeed", 10f, "Fly speed");
		mouseSens = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "MouseSens", 2f, "Mouse sensitivity");
		defaultMoveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Playback", "DefaultMoveSpeed", 10f, "Default pos speed");
		LoadPathsFromFile();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"CinematicPath Awake - Initialized");
	}

	private void OnDisable()
	{
		SavePathsToFile();
	}

	private void SavePathsToFile()
	{
		//IL_0019: 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_0025: 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_003c: Expected O, but got Unknown
		try
		{
			string contents = JsonConvert.SerializeObject((object)new PathsFile
			{
				version = 1,
				paths = savedPaths
			}, (Formatting)1, new JsonSerializerSettings
			{
				FloatFormatHandling = (FloatFormatHandling)2,
				Culture = CultureInfo.InvariantCulture,
				ReferenceLoopHandling = (ReferenceLoopHandling)1
			});
			File.WriteAllText(saveFilePath, contents);
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Saved {savedPaths.Count} paths to {saveFilePath}");
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to save paths: {arg}");
		}
	}

	private void LoadPathsFromFile()
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Expected O, but got Unknown
		if (!File.Exists(saveFilePath))
		{
			savedPaths = new Dictionary<string, List<Checkpoint>>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"No paths file found");
			return;
		}
		try
		{
			PathsFile pathsFile = JsonConvert.DeserializeObject<PathsFile>(File.ReadAllText(saveFilePath), new JsonSerializerSettings
			{
				ReferenceLoopHandling = (ReferenceLoopHandling)1
			});
			savedPaths = ((pathsFile?.paths != null) ? new Dictionary<string, List<Checkpoint>>(pathsFile.paths) : new Dictionary<string, List<Checkpoint>>());
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Loaded {savedPaths.Count} paths from file");
		}
		catch (Exception arg)
		{
			savedPaths = new Dictionary<string, List<Checkpoint>>();
			((BaseUnityPlugin)this).Logger.LogError((object)$"Failed to load paths: {arg}");
		}
	}

	private void Update()
	{
		//IL_0013: 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_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: 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_019c: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			return;
		}
		if (Input.GetKeyDown(toggleKey.Value))
		{
			ToggleFreeCam();
		}
		if (Input.GetKeyDown(playKey.Value))
		{
			if (playbackCoroutine == null)
			{
				StartPlayback(0);
			}
			else
			{
				StopPlayback();
			}
		}
		if (isPlaying)
		{
			return;
		}
		if (isFreeCam && !showAllMenu && !isEditingByFreeCam)
		{
			if (Input.GetMouseButtonDown(0))
			{
				AddCheckpoint();
			}
			if (Input.GetKeyDown(clearKey.Value))
			{
				ClearCheckpoints();
			}
			if (Input.GetMouseButtonDown(1))
			{
				if (!showAllMenu)
				{
					OpenAllMenu();
				}
				else
				{
					CloseAllMenu();
				}
			}
			HandleFreeCamInput();
		}
		if (isEditingByFreeCam)
		{
			HandleFreeCamInput();
			if (Input.GetMouseButtonDown(0))
			{
				SaveEditedCheckpoint();
			}
			else if (Input.GetMouseButtonDown(1))
			{
				CancelEditedCheckpoint();
			}
		}
		if (!isFreeCam)
		{
			return;
		}
		Cursor.lockState = (CursorLockMode)((!(Cursor.visible = showAllMenu || isEditMode)) ? 1 : 0);
		foreach (GameObject label in labels)
		{
			if (Object.op_Implicit((Object)(object)label))
			{
				label.transform.LookAt(((Component)Camera.main).transform);
				Transform transform = label.transform;
				Quaternion rotation = label.transform.rotation;
				float x = ((Quaternion)(ref rotation)).eulerAngles.x;
				rotation = label.transform.rotation;
				float num = ((Quaternion)(ref rotation)).eulerAngles.y + 180f;
				rotation = label.transform.rotation;
				transform.rotation = Quaternion.Euler(x, num, ((Quaternion)(ref rotation)).eulerAngles.z);
			}
		}
	}

	private void OnGUI()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		if (showAllMenu)
		{
			allRect = GUI.Window(3, allRect, new WindowFunction(DrawAllMenu), "All Elements Edit");
		}
		if (isEditingByFreeCam)
		{
			GUI.Label(new Rect((float)(Screen.width / 2 - 200), (float)(Screen.height - 50), 400f, 20f), "New checkpoint position. Left-click to save, right-click to cancel.");
		}
	}

	private void DrawAllMenu(int id)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: 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_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Expected O, but got Unknown
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b29: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b41: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b46: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fd: Expected O, but got Unknown
		//IL_0415: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0705: Unknown result type (might be due to invalid IL or missing references)
		//IL_070a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0712: Unknown result type (might be due to invalid IL or missing references)
		//IL_0719: Unknown result type (might be due to invalid IL or missing references)
		//IL_0723: Unknown result type (might be due to invalid IL or missing references)
		//IL_0728: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0803: Unknown result type (might be due to invalid IL or missing references)
		//IL_083e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0869: Unknown result type (might be due to invalid IL or missing references)
		//IL_0856: Unknown result type (might be due to invalid IL or missing references)
		//IL_0882: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_089a: Unknown result type (might be due to invalid IL or missing references)
		hasChanges = false;
		GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
		scrollPos = GUILayout.BeginScrollView(scrollPos, Array.Empty<GUILayoutOption>());
		for (int i = 0; i < tempCheckpoints.Count; i++)
		{
			bool num = editCPs[i].posXChanged || editCPs[i].posYChanged || editCPs[i].posZChanged || editCPs[i].yawChanged || editCPs[i].pitchChanged;
			GUIStyle val = new GUIStyle(GUI.skin.button);
			if (num)
			{
				val.normal.textColor = new Color(1f, 0.647f, 0f);
			}
			if (GUILayout.Button("Checkpoint " + (i + 1) + (expandedCPs[i] ? " ▼" : " ►"), val, Array.Empty<GUILayoutOption>()))
			{
				expandedCPs[i] = !expandedCPs[i];
			}
			if (expandedCPs[i])
			{
				GUILayout.Label("Position (X/Y/Z)", Array.Empty<GUILayoutOption>());
				string text = GUILayout.TextField(editCPs[i].posX, Array.Empty<GUILayoutOption>());
				if (text != editCPs[i].posX)
				{
					editCPs[i].posX = text;
					editCPs[i].posXChanged = true;
					hasChanges = true;
				}
				string text2 = GUILayout.TextField(editCPs[i].posY, Array.Empty<GUILayoutOption>());
				if (text2 != editCPs[i].posY)
				{
					editCPs[i].posY = text2;
					editCPs[i].posYChanged = true;
					hasChanges = true;
				}
				string text3 = GUILayout.TextField(editCPs[i].posZ, Array.Empty<GUILayoutOption>());
				if (text3 != editCPs[i].posZ)
				{
					editCPs[i].posZ = text3;
					editCPs[i].posZChanged = true;
					hasChanges = true;
				}
				GUILayout.Label("Rotation (Yaw/Pitch)", Array.Empty<GUILayoutOption>());
				string text4 = GUILayout.TextField(editCPs[i].yaw, Array.Empty<GUILayoutOption>());
				if (text4 != editCPs[i].yaw)
				{
					editCPs[i].yaw = text4;
					editCPs[i].yawChanged = true;
					hasChanges = true;
				}
				string text5 = GUILayout.TextField(editCPs[i].pitch, Array.Empty<GUILayoutOption>());
				if (text5 != editCPs[i].pitch)
				{
					editCPs[i].pitch = text5;
					editCPs[i].pitchChanged = true;
					hasChanges = true;
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Edit by Free Cam", Array.Empty<GUILayoutOption>()))
				{
					StartEditByFreeCam(i);
				}
				if (GUILayout.Button("DELETE CP", Array.Empty<GUILayoutOption>()))
				{
					tempCheckpoints.RemoveAt(i);
					RefreshEditData(resetExpanded: true);
					if (i > 0)
					{
						RecalculateSegment(tempCheckpoints, i - 1);
					}
					hasChanges = true;
				}
				GUILayout.EndHorizontal();
			}
			if (i >= tempCheckpoints.Count - 1)
			{
				continue;
			}
			bool num2 = editSegs[i].durationChanged || editSegs[i].curveAmountChanged || editSegs[i].tiltAngleChanged || editSegs[i].reverseChanged;
			GUIStyle val2 = new GUIStyle(GUI.skin.button);
			if (num2)
			{
				val2.normal.textColor = new Color(1f, 0.647f, 0f);
			}
			if (GUILayout.Button("Connection " + (i + 1) + "-" + (i + 2) + (expandedSegs[i] ? " ▼" : " ►"), val2, Array.Empty<GUILayoutOption>()))
			{
				expandedSegs[i] = !expandedSegs[i];
			}
			if (expandedSegs[i])
			{
				GUILayout.Label("Speeds (Move: " + editSegs[i].moveSpeedStr + ", Rot: " + editSegs[i].rotSpeedStr + ")", Array.Empty<GUILayoutOption>());
				GUILayout.Label("Duration (s)", Array.Empty<GUILayoutOption>());
				string text6 = GUILayout.TextField(editSegs[i].durationStr, Array.Empty<GUILayoutOption>());
				if (text6 != editSegs[i].durationStr)
				{
					editSegs[i].durationStr = text6;
					editSegs[i].durationChanged = true;
					hasChanges = true;
				}
				GUILayout.Label("Curve Amount", Array.Empty<GUILayoutOption>());
				string text7 = GUILayout.TextField(editSegs[i].curveAmountStr, Array.Empty<GUILayoutOption>());
				if (text7 != editSegs[i].curveAmountStr)
				{
					editSegs[i].curveAmountStr = text7;
					editSegs[i].curveAmountChanged = true;
					hasChanges = true;
				}
				GUILayout.Label("Tilt Angle (0-360)", Array.Empty<GUILayoutOption>());
				string text8 = GUILayout.TextField(editSegs[i].tiltAngleStr, Array.Empty<GUILayoutOption>());
				if (text8 != editSegs[i].tiltAngleStr)
				{
					editSegs[i].tiltAngleStr = text8;
					editSegs[i].tiltAngleChanged = true;
					hasChanges = true;
				}
				bool flag = GUILayout.Toggle(editSegs[i].reverseRotation, "Reverse Rotation", Array.Empty<GUILayoutOption>());
				if (flag != editSegs[i].reverseRotation)
				{
					editSegs[i].reverseRotation = flag;
					editSegs[i].reverseChanged = true;
					hasChanges = true;
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("ADD CP", Array.Empty<GUILayoutOption>()))
				{
					Checkpoint checkpoint = tempCheckpoints[i];
					Checkpoint checkpoint2 = tempCheckpoints[i + 1];
					Checkpoint item = new Checkpoint
					{
						pos = (checkpoint.pos + checkpoint2.pos) / 2f,
						rot = Quaternion.Slerp(checkpoint.rot, checkpoint2.rot, 0.5f),
						moveSpeed = defaultMoveSpeed.Value,
						rotSpeed = 90f,
						curveAmount = 0f,
						tiltAngle = 0f,
						reverseRotation = false
					};
					tempCheckpoints.Insert(i + 1, item);
					RecalculateSegment(tempCheckpoints, i);
					RecalculateSegment(tempCheckpoints, i + 1);
					RefreshEditData(resetExpanded: true);
					hasChanges = true;
				}
				if (GUILayout.Button("Reset this", Array.Empty<GUILayoutOption>()))
				{
					Checkpoint checkpoint3 = tempCheckpoints[i];
					Checkpoint checkpoint4 = tempCheckpoints[i + 1];
					float num3 = CalculateBezierLength(checkpoint3, checkpoint4, 20);
					float num4 = ((((Quaternion)(ref checkpoint4.rot)).eulerAngles.y - ((Quaternion)(ref checkpoint3.rot)).eulerAngles.y) % 360f + 360f) % 360f;
					float num5 = ((num4 > 180f) ? (num4 - 360f) : num4);
					float num6 = ((((Quaternion)(ref checkpoint3.rot)).eulerAngles.x > 180f) ? (((Quaternion)(ref checkpoint3.rot)).eulerAngles.x - 360f) : ((Quaternion)(ref checkpoint3.rot)).eulerAngles.x);
					float num7 = ((((Quaternion)(ref checkpoint4.rot)).eulerAngles.x > 180f) ? (((Quaternion)(ref checkpoint4.rot)).eulerAngles.x - 360f) : ((Quaternion)(ref checkpoint4.rot)).eulerAngles.x) - num6;
					float num8 = Mathf.Max(Mathf.Abs(num5), Mathf.Abs(num7));
					float num9 = num3 / defaultMoveSpeed.Value;
					float num10 = num8 / 90f;
					float num11 = Mathf.Max(num9, num10);
					editSegs[i].durationStr = num11.ToString("F2", CultureInfo.InvariantCulture);
					editSegs[i].durationChanged = true;
					editSegs[i].curveAmountStr = "0";
					editSegs[i].curveAmountChanged = true;
					editSegs[i].tiltAngleStr = "0";
					editSegs[i].tiltAngleChanged = true;
					editSegs[i].reverseRotation = false;
					editSegs[i].reverseChanged = true;
					hasChanges = true;
				}
				GUILayout.EndHorizontal();
			}
		}
		GUILayout.EndScrollView();
		GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Height(2f),
			GUILayout.ExpandWidth(true)
		});
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		GUILayout.Label("Start from CP:", Array.Empty<GUILayoutOption>());
		startCpStr = GUILayout.TextField(startCpStr, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
		if (GUILayout.Button("Run from CP", Array.Empty<GUILayoutOption>()))
		{
			if (int.TryParse(startCpStr, out var result) && result >= 1 && result <= tempCheckpoints.Count)
			{
				showAllMenu = false;
				isEditMode = false;
				StartPlayback(result - 1);
			}
			else
			{
				MessageHud.instance.ShowMessage((MessageType)2, "Invalid starting CP", 0, (Sprite)null, false);
			}
		}
		GUILayout.EndHorizontal();
		if (GUILayout.Button("Preview", Array.Empty<GUILayoutOption>()))
		{
			ParseTempChanges();
			UpdateVisuals(tempCheckpoints);
		}
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("Apply", Array.Empty<GUILayoutOption>()))
		{
			ParseAndApply();
			RefreshEditData();
		}
		if (GUILayout.Button("Cancel", Array.Empty<GUILayoutOption>()))
		{
			CancelAllMenu();
		}
		GUILayout.EndHorizontal();
		GUILayout.Box("", (GUILayoutOption[])(object)new GUILayoutOption[2]
		{
			GUILayout.Height(2f),
			GUILayout.ExpandWidth(true)
		});
		GUILayout.Label("Saves", Array.Empty<GUILayoutOption>());
		savesScrollPos = GUILayout.BeginScrollView(savesScrollPos, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) });
		GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
		newSaveName = GUILayout.TextField(newSaveName, Array.Empty<GUILayoutOption>());
		if (GUILayout.Button("New save", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) }) && !string.IsNullOrEmpty(newSaveName) && tempCheckpoints.Count > 0)
		{
			savedPaths[newSaveName] = tempCheckpoints.Select((Checkpoint c) => c.Clone()).ToList();
			SavePathsToFile();
			newSaveName = "";
		}
		GUILayout.EndHorizontal();
		if (savedPaths.Count > 0)
		{
			foreach (KeyValuePair<string, List<Checkpoint>> item2 in savedPaths.ToList())
			{
				string text9 = $"{item2.Key} ({item2.Value.Count} CPs)";
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(text9, Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Load", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					checkpoints = item2.Value.Select((Checkpoint c) => c.Clone()).ToList();
					tempCheckpoints = checkpoints.Select((Checkpoint c) => c.Clone()).ToList();
					originals = checkpoints.Select((Checkpoint c) => c.Clone()).ToList();
					RefreshEditData();
					UpdateVisuals();
				}
				if (GUILayout.Button("Overwrite", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }) && tempCheckpoints.Count > 0)
				{
					savedPaths[item2.Key] = tempCheckpoints.Select((Checkpoint c) => c.Clone()).ToList();
					SavePathsToFile();
				}
				if (GUILayout.Button("Delete", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
				{
					savedPaths.Remove(item2.Key);
					SavePathsToFile();
				}
				GUILayout.EndHorizontal();
			}
		}
		GUILayout.EndScrollView();
		GUILayout.EndVertical();
		GUI.DragWindow();
	}

	private void ParseTempChanges()
	{
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		HashSet<int> hashSet = new HashSet<int>();
		for (int i = 0; i < tempCheckpoints.Count; i++)
		{
			bool flag = false;
			if (float.TryParse(editCPs[i].posX.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var result) && Mathf.Abs(result - tempCheckpoints[i].pos.x) > 0.001f)
			{
				tempCheckpoints[i].pos.x = result;
				flag = true;
			}
			if (float.TryParse(editCPs[i].posY.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var result2) && Mathf.Abs(result2 - tempCheckpoints[i].pos.y) > 0.001f)
			{
				tempCheckpoints[i].pos.y = result2;
				flag = true;
			}
			if (float.TryParse(editCPs[i].posZ.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var result3) && Mathf.Abs(result3 - tempCheckpoints[i].pos.z) > 0.001f)
			{
				tempCheckpoints[i].pos.z = result3;
				flag = true;
			}
			string s = editCPs[i].yaw.Replace(',', '.');
			string s2 = editCPs[i].pitch.Replace(',', '.');
			if (float.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out var result4) && float.TryParse(s2, NumberStyles.Any, CultureInfo.InvariantCulture, out var result5))
			{
				Quaternion val = Quaternion.Euler(result5, result4, 0f);
				if (Quaternion.Angle(val, tempCheckpoints[i].rot) > 0.001f)
				{
					tempCheckpoints[i].rot = val;
					flag = true;
				}
			}
			if (flag)
			{
				if (i > 0)
				{
					hashSet.Add(i - 1);
				}
				if (i < tempCheckpoints.Count - 1)
				{
					hashSet.Add(i);
				}
			}
		}
		for (int j = 0; j < editSegs.Count; j++)
		{
			Checkpoint checkpoint = tempCheckpoints[j];
			bool flag2 = false;
			if (float.TryParse(editSegs[j].curveAmountStr.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var result6) && Mathf.Abs(result6 - checkpoint.curveAmount) > 0.001f)
			{
				checkpoint.curveAmount = result6;
				flag2 = true;
			}
			if (float.TryParse(editSegs[j].tiltAngleStr.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var result7) && Mathf.Abs(result7 - checkpoint.tiltAngle) > 0.001f)
			{
				checkpoint.tiltAngle = result7;
				flag2 = true;
			}
			if (editSegs[j].reverseRotation != checkpoint.reverseRotation)
			{
				checkpoint.reverseRotation = editSegs[j].reverseRotation;
				flag2 = true;
			}
			if (float.TryParse(editSegs[j].durationStr.Replace(',', '.'), NumberStyles.Any, CultureInfo.InvariantCulture, out var result8) && result8 > 0.1f && Mathf.Abs(result8 - editSegs[j].origDuration) > 0.001f)
			{
				hashSet.Add(j);
				flag2 = true;
			}
			if (flag2)
			{
				hashSet.Add(j);
			}
		}
		foreach (int item in hashSet)
		{
			float result9 = 0f;
			string s3 = editSegs[item].durationStr.Replace(',', '.');
			bool fromDuration = editSegs[item].durationChanged && float.TryParse(s3, NumberStyles.Any, CultureInfo.InvariantCulture, out result9);
			RecalculateSegment(tempCheckpoints, item, result9, fromDuration);
		}
	}

	private void RefreshEditData(bool resetExpanded = false)
	{
		editCPs = new List<EditCheckpoint>();
		foreach (Checkpoint tempCheckpoint in tempCheckpoints)
		{
			editCPs.Add(new EditCheckpoint(tempCheckpoint));
		}
		editSegs = new List<EditSegment>();
		for (int i = 0; i < tempCheckpoints.Count - 1; i++)
		{
			editSegs.Add(new EditSegment(tempCheckpoints[i], tempCheckpoints[i + 1]));
		}
		if (resetExpanded || expandedCPs == null || expandedCPs.Length != tempCheckpoints.Count)
		{
			expandedCPs = new bool[tempCheckpoints.Count];
			expandedSegs = new bool[tempCheckpoints.Count - 1];
		}
	}

	private void OpenAllMenu()
	{
		//IL_0098: 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)
		tempCheckpoints = checkpoints.Select((Checkpoint c) => c.Clone()).ToList();
		originals = checkpoints.Select((Checkpoint c) => c.Clone()).ToList();
		RefreshEditData();
		allRect = new Rect((float)((Screen.width - 400) / 2), (float)((Screen.height - 600) / 2), 400f, 600f);
		showAllMenu = true;
		isEditMode = true;
		startCpStr = "1";
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Opened all elements menu");
	}

	private void CloseAllMenu()
	{
		ParseAndApply();
		showAllMenu = false;
		isEditMode = false;
	}

	private void CancelAllMenu()
	{
		tempCheckpoints = originals.Select((Checkpoint c) => c.Clone()).ToList();
		checkpoints = originals.Select((Checkpoint c) => c.Clone()).ToList();
		RefreshEditData();
		UpdateVisuals();
		showAllMenu = false;
		isEditMode = false;
	}

	private void ParseAndApply()
	{
		ParseTempChanges();
		checkpoints = tempCheckpoints.Select((Checkpoint c) => c.Clone()).ToList();
		originals = checkpoints.Select((Checkpoint c) => c.Clone()).ToList();
		UpdateVisuals();
		SavePathsToFile();
	}

	public void RecalculateSegment(List<Checkpoint> cps, int index, float newDuration = 0f, bool fromDuration = false)
	{
		//IL_0032: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		if (index < 0 || index >= cps.Count - 1)
		{
			return;
		}
		Checkpoint checkpoint = cps[index];
		Checkpoint checkpoint2 = cps[index + 1];
		float num = CalculateBezierLength(checkpoint, checkpoint2, 20);
		float num2 = ((Quaternion)(ref checkpoint2.rot)).eulerAngles.y - ((Quaternion)(ref checkpoint.rot)).eulerAngles.y;
		float num3 = (num2 % 360f + 360f) % 360f;
		num2 = ((num3 > 180f) ? (num3 - 360f) : num3);
		if (checkpoint.reverseRotation)
		{
			num2 = ((num2 > 0f) ? (num2 - 360f) : (num2 + 360f));
		}
		float num4 = ((((Quaternion)(ref checkpoint.rot)).eulerAngles.x > 180f) ? (((Quaternion)(ref checkpoint.rot)).eulerAngles.x - 360f) : ((Quaternion)(ref checkpoint.rot)).eulerAngles.x);
		float num5 = ((((Quaternion)(ref checkpoint2.rot)).eulerAngles.x > 180f) ? (((Quaternion)(ref checkpoint2.rot)).eulerAngles.x - 360f) : ((Quaternion)(ref checkpoint2.rot)).eulerAngles.x) - num4;
		float num6 = Mathf.Max(Mathf.Abs(num2), Mathf.Abs(num5));
		float num7 = ((checkpoint.moveSpeed > 0f) ? checkpoint.moveSpeed : defaultMoveSpeed.Value);
		if (fromDuration && newDuration > 0.1f)
		{
			checkpoint.moveSpeed = ((num > 0f) ? (num / newDuration) : num7);
			checkpoint.rotSpeed = ((num6 > 0f) ? (num6 / newDuration) : 90f);
			return;
		}
		checkpoint.moveSpeed = num7;
		if (num > 0f)
		{
			float num8 = num / checkpoint.moveSpeed;
			checkpoint.rotSpeed = ((num6 > 0f) ? (num6 / num8) : 90f);
		}
		else
		{
			checkpoint.rotSpeed = 90f;
		}
	}

	public static float CalculateBezierLength(Checkpoint start, Checkpoint end, int segments)
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: 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_004e: 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_005e: 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_0068: 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_0070: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		Vector3 controlPoint = GetControlPoint(start, end);
		float num = 0f;
		Vector3 val = start.pos;
		for (int i = 1; i <= segments; i++)
		{
			float num2 = (float)i / (float)segments;
			Vector3 val2 = (1f - num2) * (1f - num2) * start.pos + 2f * (1f - num2) * num2 * controlPoint + num2 * num2 * end.pos;
			num += Vector3.Distance(val, val2);
			val = val2;
		}
		return num;
	}

	public static Vector3 GetControlPoint(Checkpoint start, Checkpoint end)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: 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)
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: 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_0042: 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_004b: 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_004d: 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_007a: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0084: 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_0063: 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_006e: 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_008d: 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_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_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = (start.pos + end.pos) / 2f;
		if (Mathf.Abs(start.curveAmount) > 0.01f)
		{
			Vector3 val2 = end.pos - start.pos;
			Vector3 normalized = ((Vector3)(ref val2)).normalized;
			Vector3 normalized2;
			if (!(Mathf.Abs(Vector3.Dot(normalized, Vector3.up)) < 0.99f))
			{
				val2 = Vector3.Cross(normalized, Vector3.forward);
				normalized2 = ((Vector3)(ref val2)).normalized;
			}
			else
			{
				val2 = Vector3.Cross(normalized, Vector3.up);
				normalized2 = ((Vector3)(ref val2)).normalized;
			}
			Vector3 val3 = normalized2;
			Vector3 val4 = Quaternion.AngleAxis(start.tiltAngle, normalized) * val3;
			val += val4 * start.curveAmount;
		}
		return val;
	}

	private void ToggleFreeCam()
	{
		//IL_0027: 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_0038: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected O, but got Unknown
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Expected O, but got Unknown
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: 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_00d8: Expected O, but got Unknown
		//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Expected O, but got Unknown
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Expected O, but got Unknown
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Expected O, but got Unknown
		Player localPlayer = Player.m_localPlayer;
		isFreeCam = !isFreeCam;
		if (isFreeCam)
		{
			savedPlayerPos = ((Component)localPlayer).transform.position;
			savedPlayerRot = ((Component)localPlayer).transform.rotation;
			savedGodMode = (bool)godModeField.GetValue(localPlayer);
			Rigidbody val = (Rigidbody)bodyField.GetValue(localPlayer);
			if (Object.op_Implicit((Object)(object)val))
			{
				savedKinematic = val.isKinematic;
				val.isKinematic = true;
				val.linearVelocity = Vector3.zero;
				val.angularVelocity = Vector3.zero;
			}
			((Behaviour)((Component)localPlayer).GetComponent<PlayerController>()).enabled = false;
			((Behaviour)((Component)Camera.main).GetComponent<GameCamera>()).enabled = false;
			if (hudRootField != null)
			{
				GameObject val2 = (GameObject)hudRootField.GetValue(Hud.instance);
				if (Object.op_Implicit((Object)(object)val2))
				{
					val2.SetActive(false);
				}
			}
			if (visEquipmentField != null)
			{
				object value = visEquipmentField.GetValue(localPlayer);
				if (value != null)
				{
					object? obj = value.GetType().GetField("m_visual", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value);
					GameObject val3 = (GameObject)((obj is GameObject) ? obj : null);
					if (Object.op_Implicit((Object)(object)val3))
					{
						val3.SetActive(false);
					}
				}
			}
			if (colliderField != null)
			{
				Collider val4 = (Collider)colliderField.GetValue(localPlayer);
				if (Object.op_Implicit((Object)(object)val4))
				{
					val4.enabled = false;
				}
			}
			godModeField.SetValue(localPlayer, true);
			Camera.main.nearClipPlane = 0.01f;
			UpdateVisuals();
			isEditMode = false;
			Cursor.lockState = (CursorLockMode)1;
			Cursor.visible = false;
		}
		else
		{
			((Behaviour)((Component)localPlayer).GetComponent<PlayerController>()).enabled = true;
			((Behaviour)((Component)Camera.main).GetComponent<GameCamera>()).enabled = true;
			if (hudRootField != null)
			{
				GameObject val5 = (GameObject)hudRootField.GetValue(Hud.instance);
				if (Object.op_Implicit((Object)(object)val5))
				{
					val5.SetActive(true);
				}
			}
			if (visEquipmentField != null)
			{
				object value2 = visEquipmentField.GetValue(localPlayer);
				if (value2 != null)
				{
					object? obj2 = value2.GetType().GetField("m_visual", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(value2);
					GameObject val6 = (GameObject)((obj2 is GameObject) ? obj2 : null);
					if (Object.op_Implicit((Object)(object)val6))
					{
						val6.SetActive(true);
					}
				}
			}
			if (colliderField != null)
			{
				Collider val7 = (Collider)colliderField.GetValue(localPlayer);
				if (Object.op_Implicit((Object)(object)val7))
				{
					val7.enabled = true;
				}
			}
			godModeField.SetValue(localPlayer, savedGodMode);
			Rigidbody val8 = (Rigidbody)bodyField.GetValue(localPlayer);
			if (Object.op_Implicit((Object)(object)val8))
			{
				val8.isKinematic = savedKinematic;
			}
			Camera.main.nearClipPlane = 0.3f;
			DestroyVisuals();
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
			RestorePlayerPosition();
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"FreeCam toggled: {isFreeCam}");
		MessageHud.instance.ShowMessage((MessageType)2, $"FreeCam: {isFreeCam}", 0, (Sprite)null, false);
	}

	private void HandleFreeCamInput()
	{
		//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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: 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_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = ((Component)Camera.main).transform;
		float num = Input.GetAxis("Mouse X") * mouseSens.Value;
		float num2 = Input.GetAxis("Mouse Y") * mouseSens.Value;
		if (!isEditMode)
		{
			Vector3 eulerAngles = transform.eulerAngles;
			eulerAngles.y += num;
			float x = eulerAngles.x;
			x = ((x > 180f) ? (x - 360f) : x);
			x -= num2;
			x = Mathf.Clamp(x, -89f, 89f);
			eulerAngles.x = (x + 360f) % 360f;
			transform.eulerAngles = eulerAngles;
		}
		float num3 = flySpeed.Value;
		if (Input.GetKey((KeyCode)304))
		{
			num3 *= 2f;
		}
		Vector3 val = Vector3.zero;
		val += transform.forward * Input.GetAxis("Vertical");
		val += transform.right * Input.GetAxis("Horizontal");
		val += Vector3.up * (float)(Input.GetKey((KeyCode)32) ? 1 : (Input.GetKey((KeyCode)306) ? (-1) : 0));
		if (((Vector3)(ref val)).sqrMagnitude > 0f)
		{
			((Vector3)(ref val)).Normalize();
		}
		transform.position += val * num3 * Time.deltaTime;
		ConfigEntry<float> obj = flySpeed;
		obj.Value += Input.mouseScrollDelta.y * 5f;
	}

	private void AddCheckpoint()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: 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_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e7: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = ((Component)Camera.main).transform;
		Checkpoint checkpoint = new Checkpoint
		{
			pos = transform.position,
			rot = transform.rotation,
			moveSpeed = 0f,
			rotSpeed = 0f,
			curveAmount = 0f,
			tiltAngle = 0f,
			reverseRotation = false
		};
		if (checkpoints.Count > 0)
		{
			float num = Vector3.Distance(checkpoints[checkpoints.Count - 1].pos, checkpoint.pos);
			float num2 = Quaternion.Angle(checkpoints[checkpoints.Count - 1].rot, checkpoint.rot);
			if (num > 5f || num2 > 10f)
			{
				checkpoints.Add(checkpoint);
				RecalculateSegment(checkpoints, checkpoints.Count - 2);
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Added checkpoint #{checkpoints.Count}: Pos={checkpoint.pos}, Rot={((Quaternion)(ref checkpoint.rot)).eulerAngles}");
				UpdateVisuals();
				SavePathsToFile();
				MessageHud.instance.ShowMessage((MessageType)2, $"Checkpoint #{checkpoints.Count} added", 0, (Sprite)null, false);
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Not enough changes from the previous CP #{checkpoints.Count}");
				MessageHud.instance.ShowMessage((MessageType)2, $"Not enough changes from the previous CP #{checkpoints.Count}", 0, (Sprite)null, false);
			}
		}
		else
		{
			checkpoints.Add(checkpoint);
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Added first checkpoint: Pos={checkpoint.pos}, Rot={((Quaternion)(ref checkpoint.rot)).eulerAngles}");
			UpdateVisuals();
			SavePathsToFile();
			MessageHud.instance.ShowMessage((MessageType)2, "Checkpoint #1 added", 0, (Sprite)null, false);
		}
	}

	private void ClearCheckpoints()
	{
		checkpoints.Clear();
		DestroyVisuals();
		if (playbackCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(playbackCoroutine);
		}
		playbackCoroutine = null;
		SavePathsToFile();
		MessageHud.instance.ShowMessage((MessageType)2, "All checkpoints cleared", 0, (Sprite)null, false);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Cleared all checkpoints");
	}

	private void StartPlayback(int startIndex)
	{
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: 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_005d: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007d: 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: Expected O, but got Unknown
		//IL_009d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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)
		if (checkpoints.Count >= 2 && startIndex >= 0 && startIndex < checkpoints.Count && playbackCoroutine == null)
		{
			Transform transform = ((Component)Camera.main).transform;
			Player localPlayer = Player.m_localPlayer;
			Vector3 pos = checkpoints[startIndex].pos;
			Quaternion rot = checkpoints[startIndex].rot;
			transform.position = pos;
			transform.rotation = rot;
			((Component)localPlayer).transform.position = pos;
			((Component)localPlayer).transform.rotation = rot;
			Rigidbody val = (Rigidbody)bodyField.GetValue(localPlayer);
			if (Object.op_Implicit((Object)(object)val))
			{
				val.position = pos;
				val.rotation = rot;
				val.linearVelocity = Vector3.zero;
				val.angularVelocity = Vector3.zero;
			}
			DestroyVisuals();
			isPlaying = true;
			playbackCoroutine = ((MonoBehaviour)this).StartCoroutine(PlaybackRoutine(startIndex));
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Playback started from checkpoint #{startIndex + 1}");
		}
	}

	private void StopPlayback()
	{
		if (playbackCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(playbackCoroutine);
			playbackCoroutine = null;
		}
		isPlaying = false;
		RestorePlayerPosition();
		UpdateVisuals();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Playback stopped");
	}

	private IEnumerator PlaybackRoutine(int startIndex)
	{
		Transform cam = ((Component)Camera.main).transform;
		Player player = Player.m_localPlayer;
		Rigidbody body = (Rigidbody)bodyField.GetValue(player);
		for (int i = startIndex; i < checkpoints.Count - 1; i++)
		{
			Checkpoint start = checkpoints[i];
			Checkpoint end = checkpoints[i + 1];
			float moveSpeed = start.moveSpeed;
			float rotSpeed = start.rotSpeed;
			float num = CalculateBezierLength(start, end, 20);
			float deltaYaw2 = ((Quaternion)(ref end.rot)).eulerAngles.y - ((Quaternion)(ref start.rot)).eulerAngles.y;
			float num2 = (deltaYaw2 % 360f + 360f) % 360f;
			deltaYaw2 = ((num2 > 180f) ? (num2 - 360f) : num2);
			if (start.reverseRotation)
			{
				deltaYaw2 = ((deltaYaw2 > 0f) ? (deltaYaw2 - 360f) : (deltaYaw2 + 360f));
			}
			float num3 = ((((Quaternion)(ref start.rot)).eulerAngles.x > 180f) ? (((Quaternion)(ref start.rot)).eulerAngles.x - 360f) : ((Quaternion)(ref start.rot)).eulerAngles.x);
			float num4 = ((((Quaternion)(ref end.rot)).eulerAngles.x > 180f) ? (((Quaternion)(ref end.rot)).eulerAngles.x - 360f) : ((Quaternion)(ref end.rot)).eulerAngles.x);
			float deltaPitch = num4 - num3;
			float num5 = Mathf.Max(Mathf.Abs(deltaYaw2), Mathf.Abs(deltaPitch));
			if (num <= 0.01f && num5 <= 0.1f)
			{
				continue;
			}
			float num6 = ((num > 0.01f) ? (num / moveSpeed) : 0f);
			float num7 = ((num5 > 0.1f) ? (num5 / rotSpeed) : 0f);
			float duration = Mathf.Max(num6, num7);
			Vector3 control = GetControlPoint(start, end);
			float t2 = 0f;
			while (t2 < 1f)
			{
				t2 += Time.deltaTime / duration;
				t2 = Mathf.Clamp01(t2);
				Vector3 position = (1f - t2) * (1f - t2) * start.pos + 2f * (1f - t2) * t2 * control + t2 * t2 * end.pos;
				float num8 = ((Quaternion)(ref start.rot)).eulerAngles.y + t2 * deltaYaw2;
				Quaternion rotation = Quaternion.Euler(((Quaternion)(ref start.rot)).eulerAngles.x + t2 * deltaPitch, num8, 0f);
				cam.position = position;
				cam.rotation = rotation;
				((Component)player).transform.position = position;
				((Component)player).transform.rotation = rotation;
				if (Object.op_Implicit((Object)(object)body))
				{
					body.position = position;
					body.rotation = rotation;
					body.linearVelocity = Vector3.zero;
					body.angularVelocity = Vector3.zero;
				}
				yield return null;
			}
		}
		playbackCoroutine = null;
		isPlaying = false;
		RestorePlayerPosition();
		UpdateVisuals();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Playback finished");
	}

	private void RestorePlayerPosition()
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_001e: 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_007b: 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_004f: 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_0065: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		Rigidbody val = (Rigidbody)bodyField.GetValue(localPlayer);
		((Component)localPlayer).transform.position = savedPlayerPos;
		((Component)localPlayer).transform.rotation = savedPlayerRot;
		if (Object.op_Implicit((Object)(object)val))
		{
			val.position = savedPlayerPos;
			val.rotation = savedPlayerRot;
			val.linearVelocity = Vector3.zero;
			val.angularVelocity = Vector3.zero;
		}
		maxAirAltitudeField.SetValue(localPlayer, ((Component)localPlayer).transform.position.y);
		lastGroundTouchField.SetValue(localPlayer, Time.time);
	}

	private void UpdateVisuals(List<Checkpoint> cps = null)
	{
		//IL_00ea: 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_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0141: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Expected O, but got Unknown
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0268: Expected O, but got Unknown
		//IL_0278: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_030d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0323: Unknown result type (might be due to invalid IL or missing references)
		//IL_0325: Unknown result type (might be due to invalid IL or missing references)
		//IL_032a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0336: Unknown result type (might be due to invalid IL or missing references)
		//IL_033b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0340: Unknown result type (might be due to invalid IL or missing references)
		//IL_0345: Unknown result type (might be due to invalid IL or missing references)
		//IL_0350: Unknown result type (might be due to invalid IL or missing references)
		//IL_0365: Unknown result type (might be due to invalid IL or missing references)
		//IL_036a: Unknown result type (might be due to invalid IL or missing references)
		//IL_036e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0373: Unknown result type (might be due to invalid IL or missing references)
		//IL_0375: Unknown result type (might be due to invalid IL or missing references)
		//IL_0377: Unknown result type (might be due to invalid IL or missing references)
		//IL_0399: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Expected O, but got Unknown
		//IL_03db: Unknown result type (might be due to invalid IL or missing references)
		//IL_03dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_03df: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_040e: Unknown result type (might be due to invalid IL or missing references)
		//IL_043f: Unknown result type (might be due to invalid IL or missing references)
		if (cps == null)
		{
			cps = checkpoints;
		}
		DestroyVisuals();
		if (cps.Count == 0)
		{
			return;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)$"Updating visuals for {cps.Count} checkpoints");
		Font val = ((IEnumerable<Font>)Resources.FindObjectsOfTypeAll<Font>()).FirstOrDefault((Func<Font, bool>)((Font f) => ((Object)f).name == "AveriaSerifLibre-Regular")) ?? ((IEnumerable<Font>)Resources.FindObjectsOfTypeAll<Font>()).FirstOrDefault((Func<Font, bool>)((Font f) => ((Object)f).name == "Arial")) ?? Resources.FindObjectsOfTypeAll<Font>().FirstOrDefault();
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"No suitable font found for TextMesh. Labels may not render.");
		}
		for (int i = 0; i < cps.Count; i++)
		{
			GameObject val2 = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)val2).name = "CPMarker" + i;
			val2.transform.position = cps[i].pos;
			val2.transform.localScale = Vector3.one * 1.3333334f;
			val2.GetComponent<Renderer>().material = CreateTransparentMaterial(Color.red);
			markers.Add(val2);
			GameObject val3 = new GameObject("LabelCP" + i);
			TextMesh val4 = val3.AddComponent<TextMesh>();
			val4.text = (i + 1).ToString();
			((Component)val4).transform.position = cps[i].pos + Vector3.up * 1f;
			((Component)val4).transform.rotation = Quaternion.identity;
			val4.characterSize = 0.1f;
			val4.fontSize = 120;
			val4.alignment = (TextAlignment)1;
			val4.anchor = (TextAnchor)4;
			val4.color = Color.white;
			if (Object.op_Implicit((Object)(object)val))
			{
				val4.font = val;
			}
			val4.richText = false;
			MeshRenderer val5 = val3.GetComponent<MeshRenderer>() ?? val3.AddComponent<MeshRenderer>();
			if ((Object)(object)val4.font != (Object)null && (Object)(object)val4.font.material != (Object)null)
			{
				((Renderer)val5).material = val4.font.material;
			}
			labels.Add(val3);
		}
		if (cps.Count < 2)
		{
			return;
		}
		pathLine = new GameObject("PathLine");
		LineRenderer val6 = pathLine.AddComponent<LineRenderer>();
		((Renderer)val6).material = CreateTransparentMaterial(Color.white);
		float startWidth = (val6.endWidth = 1f / 3f);
		val6.startWidth = startWidth;
		int num2 = 20;
		val6.positionCount = (cps.Count - 1) * num2 + 1;
		int num3 = 0;
		for (int j = 0; j < cps.Count - 1; j++)
		{
			Checkpoint checkpoint = cps[j];
			Checkpoint checkpoint2 = cps[j + 1];
			Vector3 controlPoint = GetControlPoint(checkpoint, checkpoint2);
			for (int k = ((j != 0) ? 1 : 0); k <= num2; k++)
			{
				float num4 = (float)k / (float)num2;
				Vector3 val7 = (1f - num4) * (1f - num4) * checkpoint.pos + 2f * (1f - num4) * num4 * controlPoint + num4 * num4 * checkpoint2.pos;
				val6.SetPosition(num3++, val7);
			}
			Vector3 pos = checkpoint.pos;
			Vector3 pos2 = checkpoint2.pos;
			if (Vector3.Distance(pos, pos2) > 0f)
			{
				GameObject val8 = new GameObject("LabelSeg" + j);
				TextMesh val9 = val8.AddComponent<TextMesh>();
				val9.text = j + 1 + "-" + (j + 2);
				((Component)val9).transform.position = (pos + pos2) / 2f + Vector3.up * 1f;
				((Component)val9).transform.rotation = Quaternion.identity;
				val9.characterSize = 0.1f;
				val9.fontSize = 120;
				val9.alignment = (TextAlignment)1;
				val9.anchor = (TextAnchor)4;
				val9.color = Color.white;
				if (Object.op_Implicit((Object)(object)val))
				{
					val9.font = val;
				}
				val9.richText = false;
				MeshRenderer val10 = val8.GetComponent<MeshRenderer>() ?? val8.AddComponent<MeshRenderer>();
				if ((Object)(object)val9.font != (Object)null && (Object)(object)val9.font.material != (Object)null)
				{
					((Renderer)val10).material = val9.font.material;
				}
				labels.Add(val8);
			}
		}
	}

	private void DestroyVisuals()
	{
		foreach (GameObject marker in markers)
		{
			if (Object.op_Implicit((Object)(object)marker))
			{
				Object.Destroy((Object)(object)marker);
			}
		}
		markers.Clear();
		foreach (GameObject segmentCollider in segmentColliders)
		{
			if (Object.op_Implicit((Object)(object)segmentCollider))
			{
				Object.Destroy((Object)(object)segmentCollider);
			}
		}
		segmentColliders.Clear();
		foreach (GameObject label in labels)
		{
			if (Object.op_Implicit((Object)(object)label))
			{
				Object.Destroy((Object)(object)label);
			}
		}
		labels.Clear();
		if (Object.op_Implicit((Object)(object)pathLine))
		{
			Object.Destroy((Object)(object)pathLine);
		}
		pathLine = null;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Visuals destroyed");
	}

	private Material CreateTransparentMaterial(Color color)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Expected O, but got Unknown
		//IL_0089: 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_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0071: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		Shader val = Shader.Find("Unlit/Transparent") ?? Shader.Find("Legacy Shaders/Transparent/Diffuse") ?? Shader.Find("Diffuse");
		if ((Object)(object)val == (Object)null)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"No suitable shader found, using Diffuse fallback");
			val = Shader.Find("Diffuse");
		}
		Material val2 = new Material(val);
		if (((Object)val).name.Contains("Transparent"))
		{
			val2.color = new Color(color.r, color.g, color.b, 0.5f);
		}
		else
		{
			val2.color = color;
		}
		return val2;
	}

	private void StartEditByFreeCam(int index)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: 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)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: 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)
		showAllMenu = false;
		isEditMode = false;
		Transform transform = ((Component)Camera.main).transform;
		savedCamPos = transform.position;
		savedCamRot = transform.rotation;
		transform.position = tempCheckpoints[index].pos;
		transform.rotation = tempCheckpoints[index].rot;
		isEditingByFreeCam = true;
		editingCheckpointIndex = index;
		Cursor.lockState = (CursorLockMode)1;
		Cursor.visible = false;
	}

	private void SaveEditedCheckpoint()
	{
		//IL_0027: 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_0043: 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_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		if (editingCheckpointIndex != -1)
		{
			Transform transform = ((Component)Camera.main).transform;
			tempCheckpoints[editingCheckpointIndex].pos = transform.position;
			tempCheckpoints[editingCheckpointIndex].rot = transform.rotation;
			if (editingCheckpointIndex > 0)
			{
				RecalculateSegment(tempCheckpoints, editingCheckpointIndex - 1);
			}
			if (editingCheckpointIndex < tempCheckpoints.Count - 1)
			{
				RecalculateSegment(tempCheckpoints, editingCheckpointIndex);
			}
			transform.position = savedCamPos;
			transform.rotation = savedCamRot;
			showAllMenu = true;
			isEditMode = true;
			RefreshEditData();
			isEditingByFreeCam = false;
			editingCheckpointIndex = -1;
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}
	}

	private void CancelEditedCheckpoint()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		Transform transform = ((Component)Camera.main).transform;
		transform.position = savedCamPos;
		transform.rotation = savedCamRot;
		showAllMenu = true;
		isEditMode = true;
		isEditingByFreeCam = false;
		editingCheckpointIndex = -1;
		Cursor.lockState = (CursorLockMode)0;
		Cursor.visible = true;
	}
}
[Serializable]
public class PathsFile
{
	public int version;

	public Dictionary<string, List<Checkpoint>> paths;
}
[Serializable]
public class Checkpoint
{
	[SerializeField]
	public Vector3 pos;

	[SerializeField]
	public Quaternion rot;

	[SerializeField]
	public float moveSpeed;

	[SerializeField]
	public float rotSpeed;

	[SerializeField]
	public float curveAmount;

	[SerializeField]
	public float tiltAngle;

	[SerializeField]
	public bool reverseRotation;

	public Checkpoint Clone()
	{
		//IL_0007: 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_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		return new Checkpoint
		{
			pos = pos,
			rot = rot,
			moveSpeed = moveSpeed,
			rotSpeed = rotSpeed,
			curveAmount = curveAmount,
			tiltAngle = tiltAngle,
			reverseRotation = reverseRotation
		};
	}
}
public class EditCheckpoint
{
	public string posX;

	public string posY;

	public string posZ;

	public string yaw;

	public string pitch;

	public bool posXChanged;

	public bool posYChanged;

	public bool posZChanged;

	public bool yawChanged;

	public bool pitchChanged;

	public EditCheckpoint(Checkpoint cp)
	{
		//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_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)
		posX = cp.pos.x.ToString("F2", CultureInfo.InvariantCulture);
		posY = cp.pos.y.ToString("F2", CultureInfo.InvariantCulture);
		posZ = cp.pos.z.ToString("F2", CultureInfo.InvariantCulture);
		yaw = ((Quaternion)(ref cp.rot)).eulerAngles.y.ToString("F2", CultureInfo.InvariantCulture);
		pitch = ((Quaternion)(ref cp.rot)).eulerAngles.x.ToString("F2", CultureInfo.InvariantCulture);
	}

	public void Reset()
	{
		posXChanged = (posYChanged = (posZChanged = (yawChanged = (pitchChanged = false))));
	}
}
public class EditSegment
{
	public string moveSpeedStr;

	public string rotSpeedStr;

	public string durationStr;

	public string curveAmountStr;

	public string tiltAngleStr;

	public float origDuration;

	public float origCurveAmount;

	public float origTiltAngle;

	public bool reverseRotation;

	public bool durationChanged;

	public bool curveAmountChanged;

	public bool tiltAngleChanged;

	public bool reverseChanged;

	public EditSegment(Checkpoint start, Checkpoint end)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: 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_0097: 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_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		float num = CinematicPath.CalculateBezierLength(start, end, 20);
		float num2 = ((Quaternion)(ref end.rot)).eulerAngles.y - ((Quaternion)(ref start.rot)).eulerAngles.y;
		float num3 = (num2 % 360f + 360f) % 360f;
		num2 = ((num3 > 180f) ? (num3 - 360f) : num3);
		if (start.reverseRotation)
		{
			num2 = ((num2 > 0f) ? (num2 - 360f) : (num2 + 360f));
		}
		float num4 = ((((Quaternion)(ref start.rot)).eulerAngles.x > 180f) ? (((Quaternion)(ref start.rot)).eulerAngles.x - 360f) : ((Quaternion)(ref start.rot)).eulerAngles.x);
		float num5 = ((((Quaternion)(ref end.rot)).eulerAngles.x > 180f) ? (((Quaternion)(ref end.rot)).eulerAngles.x - 360f) : ((Quaternion)(ref end.rot)).eulerAngles.x) - num4;
		float num6 = Mathf.Max(Mathf.Abs(num2), Mathf.Abs(num5));
		origDuration = Mathf.Max((start.moveSpeed > 0f) ? (num / start.moveSpeed) : 0f, (start.rotSpeed > 0f) ? (num6 / start.rotSpeed) : 0f);
		origCurveAmount = start.curveAmount;
		origTiltAngle = start.tiltAngle;
		reverseRotation = start.reverseRotation;
		moveSpeedStr = start.moveSpeed.ToString("F2", CultureInfo.InvariantCulture);
		rotSpeedStr = start.rotSpeed.ToString("F2", CultureInfo.InvariantCulture);
		durationStr = origDuration.ToString("F2", CultureInfo.InvariantCulture);
		curveAmountStr = origCurveAmount.ToString("F2", CultureInfo.InvariantCulture);
		tiltAngleStr = origTiltAngle.ToString("F2", CultureInfo.InvariantCulture);
	}

	public void Reset()
	{
		durationChanged = (curveAmountChanged = (tiltAngleChanged = (reverseChanged = false)));
	}
}
public static class ReflectionExtensions
{
	public static T GetFieldValue<T>(this object obj, string name)
	{
		return (T)(AccessTools.Field(obj.GetType(), name)?.GetValue(obj));
	}
}