Decompiled source of LOSMIRAGEBOYS v0.6.4

BepInEx/plugins/Ruta3Company/Ruta3Company.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Ruta3Company.Models;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Ruta3Company")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Ruta3Company")]
[assembly: AssemblyTitle("Ruta3Company")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Ruta3Company
{
	internal sealed class CameraVisibility<T> where T : class
	{
		private sealed class Frame
		{
			public object Camera;

			public Dictionary<T, bool> Values = new Dictionary<T, bool>();
		}

		private readonly Stack<Frame> frames = new Stack<Frame>();

		private readonly Func<T, bool> read;

		private readonly Action<T, bool> write;

		public int Depth => frames.Count;

		public CameraVisibility(Func<T, bool> read, Action<T, bool> write)
		{
			this.read = read;
			this.write = write;
		}

		public void Begin(object camera, IEnumerable<KeyValuePair<T, bool>> values)
		{
			Frame frame = new Frame
			{
				Camera = camera
			};
			frames.Push(frame);
			foreach (KeyValuePair<T, bool> value in values)
			{
				if (!frame.Values.ContainsKey(value.Key))
				{
					frame.Values.Add(value.Key, read(value.Key));
				}
				write(value.Key, value.Value);
			}
		}

		public void End(object camera)
		{
			if (frames.Count != 0 && frames.Peek().Camera == camera)
			{
				Restore(frames.Pop());
			}
		}

		private void Restore(Frame frame)
		{
			foreach (KeyValuePair<T, bool> value in frame.Values)
			{
				write(value.Key, value.Value);
			}
		}

		public void Clear()
		{
			while (frames.Count > 0)
			{
				Restore(frames.Pop());
			}
		}
	}
	[BepInPlugin("sv.rudy.ruta3company", "LOSMIRAGEBOYS", "0.6.4")]
	[BepInProcess("Lethal Company.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private void Awake()
		{
			ModRuntime.Start(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger);
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)((ModRuntime.Instance == null) ? "Host Unity destruido; runtime Ruta3 no estaba activo." : "Host Unity destruido; runtime Ruta3 permanece activo hasta cerrar el juego."));
		}
	}
	internal sealed class ModRuntime
	{
		private sealed class DoorMotion
		{
			public Transform Pivot;

			public AnimatedObjectTrigger Trigger;

			public int Side;

			public bool Bus;

			public float Open;

			public Vector3 Closed;
		}

		private sealed class VisualMount
		{
			public Transform Root;

			public Transform Follow;

			public Vector3 LocalPosition;

			public Quaternion LocalRotation;

			public Collider Interior;

			public VehicleController Vehicle;

			public Renderer[] Skin;

			public readonly List<Renderer> Originals = new List<Renderer>();
		}

		[HarmonyPatch(typeof(StartOfRound), "Update")]
		private static class RoundTick
		{
			[HarmonyPostfix]
			private static void Postfix()
			{
				if (Instance != null)
				{
					if (!roundHookReported)
					{
						roundHookReported = true;
						Instance.Logger.LogInfo((object)"Enganche de partida ejecutado.");
					}
					Instance.Scan();
					Instance.FollowVisuals();
					Instance.ApplyDefaultVisibility();
				}
			}
		}

		[HarmonyPatch(typeof(VehicleController), "Update")]
		private static class VehicleTick
		{
			[HarmonyPostfix]
			private static void Postfix(VehicleController __instance)
			{
				if (Instance != null)
				{
					Instance.Scan();
					Instance.FollowVisuals();
					Instance.ApplyDefaultVisibility();
				}
			}
		}

		private readonly ConfigFile Config;

		private readonly ManualLogSource Logger;

		private ConfigEntry<bool> mirage;

		private ConfigEntry<bool> bus;

		private ConfigEntry<bool> hideBody;

		private ConfigEntry<Vector3> carOffset;

		private ConfigEntry<Vector3> carScale;

		private ConfigEntry<Vector3> busOffset;

		private ConfigEntry<Vector3> busSize;

		private ConfigEntry<float> carYaw;

		private ConfigEntry<float> busYaw;

		private readonly List<GameObject> roots = new List<GameObject>();

		private readonly Dictionary<Renderer, bool> originals = new Dictionary<Renderer, bool>();

		private readonly List<Material> materials = new List<Material>();

		private readonly List<Mesh> meshes = new List<Mesh>();

		private readonly Dictionary<string, Material> palette = new Dictionary<string, Material>();

		private readonly HashSet<Transform> mounted = new HashSet<Transform>();

		private float nextScan;

		private readonly List<VisualMount> visuals = new List<VisualMount>();

		private readonly CameraVisibility<Renderer> cameraVisibility = new CameraVisibility<Renderer>((Renderer r) => Object.op_Implicit((Object)(object)r) && r.forceRenderingOff, delegate(Renderer r, bool value)
		{
			if (Object.op_Implicit((Object)(object)r))
			{
				r.forceRenderingOff = value;
			}
		});

		private bool cameraReported;

		private readonly List<DoorMotion> doors = new List<DoorMotion>();

		private int doorFrame = -1;

		internal static ModRuntime Instance;

		private Harmony hooks;

		private bool tickReported;

		private static bool roundHookReported;

		private ModRuntime(ConfigFile config, ManualLogSource logger)
		{
			Config = config;
			Logger = logger;
		}

		internal static void Start(ConfigFile config, ManualLogSource logger)
		{
			if (Instance != null)
			{
				return;
			}
			ModRuntime modRuntime = (Instance = new ModRuntime(config, logger));
			try
			{
				modRuntime.Initialize();
			}
			catch
			{
				modRuntime.Shutdown();
				throw;
			}
		}

		private void Initialize()
		{
			//IL_0083: 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_00f5: 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_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_02db: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Expected O, but got Unknown
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_031f: Expected O, but got Unknown
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_035a: Expected O, but got Unknown
			//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0402: Expected O, but got Unknown
			//IL_0402: Unknown result type (might be due to invalid IL or missing references)
			//IL_040c: Expected O, but got Unknown
			//IL_0418: Unknown result type (might be due to invalid IL or missing references)
			//IL_0422: Expected O, but got Unknown
			//IL_0422: Unknown result type (might be due to invalid IL or missing references)
			//IL_042c: Expected O, but got Unknown
			mirage = Config.Bind<bool>("General", "Mirage", true, "Carroceria experimental del Mirage.");
			bus = Config.Bind<bool>("General", "Ruta3", true, "Carroceria exterior experimental; requiere ajustar posicion en juego.");
			hideBody = Config.Bind<bool>("Mirage", "OcultarCarroceriaOriginal", true, "Oculta las mallas originales desde fuera; conserva ruedas, colliders y mecanicas. Restaura el interior por camara.");
			carOffset = Config.Bind<Vector3>("Mirage", "Posicion", new Vector3(0f, 0f, 0f), (ConfigDescription)null);
			carScale = Config.Bind<Vector3>("Mirage", "Escala", Vector3.one, (ConfigDescription)null);
			carYaw = Config.Bind<float>("Mirage", "GiroY", 0f, (ConfigDescription)null);
			busOffset = Config.Bind<Vector3>("Ruta3", "PosicionRespectoAlCentroInterior", new Vector3(0f, 0f, 0f), (ConfigDescription)null);
			busSize = Config.Bind<Vector3>("Ruta3", "Tamano", new Vector3(5.5f, 4.2f, 11f), "Grande para envolver el interior original. X ancho, Y alto, Z largo.");
			busYaw = Config.Bind<float>("Ruta3", "GiroY", 0f, (ConfigDescription)null);
			Color color = default(Color);
			foreach (KeyValuePair<string, string> color2 in Factory.Colors)
			{
				if (ColorUtility.TryParseHtmlString(color2.Value, ref color))
				{
					Material val = Mat(color, color2.Key == "cyan" || color2.Key == "pink");
					if (val.HasProperty("_Metallic"))
					{
						val.SetFloat("_Metallic", (color2.Key == "chrome") ? 0.82f : ((color2.Key == "aqua") ? 0.16f : 0f));
					}
					if (val.HasProperty("_Smoothness"))
					{
						val.SetFloat("_Smoothness", (color2.Key == "chrome") ? 0.75f : ((color2.Key == "glass" || color2.Key == "lens") ? 0.83f : ((color2.Key == "aqua") ? 0.58f : ((color2.Key == "white") ? 0.5f : 0.3f))));
					}
					palette.Add(color2.Key, val);
				}
			}
			hooks = new Harmony("sv.rudy.ruta3company");
			hooks.Patch((MethodBase)AccessTools.Method(typeof(StartOfRound), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(RoundTick), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			hooks.Patch((MethodBase)AccessTools.Method(typeof(VehicleController), "Update", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(VehicleTick), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			int num = hooks.GetPatchedMethods().Count();
			Logger.LogInfo((object)("LOSMIRAGEBOYS 0.6.4: metodos enganchados=" + num + "; sin rotulos; visibilidad por camara"));
			if (num != 2)
			{
				throw new InvalidOperationException("Se esperaban 2 enganches; instalados=" + num);
			}
			SceneManager.sceneLoaded += SceneLoaded;
			Application.quitting += Shutdown;
			RenderPipelineManager.beginCameraRendering += BeforeCamera;
			RenderPipelineManager.endCameraRendering += AfterCamera;
			Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(BeforeLegacy));
			Camera.onPostRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(AfterLegacy));
			Scan();
		}

		private void SceneLoaded(Scene scene, LoadSceneMode mode)
		{
			Logger.LogInfo((object)("Escena cargada: " + ((Scene)(ref scene)).name + "; runtime Ruta3 activo"));
			nextScan = 0f;
			Scan();
		}

		private Material Mat(Color color, bool glow = false)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: 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)
			Shader obj = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard") ?? Shader.Find("Unlit/Color");
			if (!Object.op_Implicit((Object)(object)obj))
			{
				throw new InvalidOperationException("No se encontro shader compatible.");
			}
			Material val = new Material(obj);
			val.color = color;
			if (val.HasProperty("_BaseColor"))
			{
				val.SetColor("_BaseColor", color);
			}
			if (glow)
			{
				val.EnableKeyword("_EMISSION");
				if (val.HasProperty("_EmissionColor"))
				{
					val.SetColor("_EmissionColor", color * 3f);
				}
				if (val.HasProperty("_EmissiveColor"))
				{
					val.SetColor("_EmissiveColor", color * 8f);
				}
			}
			materials.Add(val);
			return val;
		}

		internal void Scan()
		{
			if (Time.realtimeSinceStartup < nextScan)
			{
				return;
			}
			nextScan = Time.realtimeSinceStartup + 3f;
			if (!tickReported)
			{
				tickReported = true;
				Logger.LogInfo((object)("Rutina de montaje activa. Mirage=" + mirage.Value + "; Ruta3=" + bus.Value));
			}
			try
			{
				mounted.RemoveWhere((Transform t) => !Object.op_Implicit((Object)(object)t));
				if (mirage.Value)
				{
					VehicleController[] array = Object.FindObjectsOfType<VehicleController>();
					foreach (VehicleController val in array)
					{
						if (!mounted.Contains(((Component)val).transform))
						{
							MakeMirage(val);
						}
					}
				}
				StartOfRound instance = StartOfRound.Instance;
				if (bus.Value && Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.shipInnerRoomBounds))
				{
					Transform transform = ((Component)instance.shipInnerRoomBounds).transform;
					if (!mounted.Contains(transform))
					{
						MakeBus(transform, instance.shipInnerRoomBounds);
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("Fallo de montaje: " + ex));
				nextScan = Time.realtimeSinceStartup + 30f;
			}
		}

		private Transform Root(string name, Transform parent)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			roots.Add(val);
			val.transform.SetParent(parent, false);
			return val.transform;
		}

		private void Register(VisualMount mount, Renderer r)
		{
			if (Object.op_Implicit((Object)(object)r) && !mount.Originals.Contains(r))
			{
				if (!originals.ContainsKey(r))
				{
					originals.Add(r, r.forceRenderingOff);
				}
				mount.Originals.Add(r);
			}
		}

		private void FollowVisuals()
		{
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			visuals.RemoveAll((VisualMount m) => !Object.op_Implicit((Object)(object)m.Root));
			foreach (VisualMount visual in visuals)
			{
				if (Object.op_Implicit((Object)(object)visual.Follow))
				{
					visual.Root.position = visual.Follow.TransformPoint(visual.LocalPosition);
					visual.Root.rotation = visual.Follow.rotation * visual.LocalRotation;
				}
			}
			if (doorFrame == Time.frameCount)
			{
				return;
			}
			doorFrame = Time.frameCount;
			doors.RemoveAll((DoorMotion d) => !Object.op_Implicit((Object)(object)d.Pivot));
			foreach (DoorMotion door in doors)
			{
				StartOfRound instance = StartOfRound.Instance;
				bool flag = ((!door.Bus) ? (Object.op_Implicit((Object)(object)door.Trigger) && door.Trigger.boolValue) : (Object.op_Implicit((Object)(object)instance) && !instance.hangarDoorsClosed));
				door.Open = Mathf.MoveTowards(door.Open, (float)(flag ? 1 : 0), Time.deltaTime * 2.6f);
				if (door.Bus)
				{
					door.Pivot.localPosition = door.Closed + Vector3.right * ((float)door.Side * 0.52f * door.Open);
				}
				else
				{
					door.Pivot.localRotation = Quaternion.Euler(0f, (float)(-door.Side) * 68f * door.Open, 0f);
				}
			}
		}

		private void BeforeCamera(ScriptableRenderContext context, Camera camera)
		{
			ApplyCamera(camera);
		}

		private void AfterCamera(ScriptableRenderContext context, Camera camera)
		{
			cameraVisibility.End(camera);
		}

		private void BeforeLegacy(Camera camera)
		{
			if (!Object.op_Implicit((Object)(object)GraphicsSettings.currentRenderPipeline))
			{
				ApplyCamera(camera);
			}
		}

		private void AfterLegacy(Camera camera)
		{
			if (!Object.op_Implicit((Object)(object)GraphicsSettings.currentRenderPipeline))
			{
				cameraVisibility.End(camera);
			}
		}

		private void ApplyCamera(Camera camera)
		{
			if (Object.op_Implicit((Object)(object)camera))
			{
				FollowVisuals();
				cameraVisibility.Begin(camera, CameraValues(camera));
				if (!cameraReported)
				{
					cameraReported = true;
					Logger.LogInfo((object)("VISIBILIDAD: callbacks de camara activos; camara=" + ((Object)camera).name + "; restauracion anidada y exterior persistente."));
				}
			}
		}

		private void ApplyDefaultVisibility()
		{
			if (cameraVisibility.Depth != 0)
			{
				return;
			}
			StartOfRound instance = StartOfRound.Instance;
			Camera camera = ((Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.localPlayerController)) ? instance.localPlayerController.gameplayCamera : null);
			foreach (KeyValuePair<Renderer, bool> item in CameraValues(camera))
			{
				if (Object.op_Implicit((Object)(object)item.Key))
				{
					item.Key.forceRenderingOff = item.Value;
				}
			}
		}

		private IEnumerable<KeyValuePair<Renderer, bool>> CameraValues(Camera camera)
		{
			foreach (VisualMount m in visuals)
			{
				bool inside = false;
				if (Object.op_Implicit((Object)(object)camera) && Object.op_Implicit((Object)(object)m.Vehicle))
				{
					Vector3 val = m.Root.InverseTransformPoint(((Component)camera).transform.position);
					inside = Mathf.Abs(val.x) < 0.89f && val.y > 0.7f && val.y < 1.85f && val.z > -1.7f && val.z < 1.05f;
					if (m.Vehicle.carDestroyed)
					{
						inside = true;
					}
				}
				else if (Object.op_Implicit((Object)(object)camera) && Object.op_Implicit((Object)(object)m.Interior))
				{
					Bounds bounds = m.Interior.bounds;
					((Bounds)(ref bounds)).Expand(0.65f);
					inside = ((Bounds)(ref bounds)).Contains(((Component)camera).transform.position);
				}
				Renderer[] skin = m.Skin;
				foreach (Renderer val2 in skin)
				{
					if (Object.op_Implicit((Object)(object)val2))
					{
						yield return new KeyValuePair<Renderer, bool>(val2, inside);
					}
				}
				foreach (Renderer original in m.Originals)
				{
					if (Object.op_Implicit((Object)(object)original))
					{
						yield return new KeyValuePair<Renderer, bool>(original, !inside || originals[original]);
					}
				}
			}
		}

		private void ResetCamera()
		{
			cameraVisibility.Clear();
			foreach (VisualMount visual in visuals)
			{
				Renderer[] skin = visual.Skin;
				foreach (Renderer val in skin)
				{
					if (Object.op_Implicit((Object)(object)val))
					{
						val.forceRenderingOff = false;
					}
				}
			}
			foreach (KeyValuePair<Renderer, bool> original in originals)
			{
				if (Object.op_Implicit((Object)(object)original.Key))
				{
					original.Key.forceRenderingOff = original.Value;
				}
			}
		}

		private void Geometry(Transform root, List<Part> parts, bool includeWheels, int layer, bool twoSided = false)
		{
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			//IL_0389: Unknown result type (might be due to invalid IL or missing references)
			//IL_038e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0396: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			foreach (IGrouping<string, Part> item in from p in parts
				where includeWheels || !p.Wheel
				group p by p.Material)
			{
				List<Vector3> list = new List<Vector3>();
				List<int> list2 = new List<int>();
				foreach (Part item2 in item)
				{
					bool flag = item2.Name.Contains("Body") || item2.Name.Contains("Roof") || item2.Name.Contains("RoundedMirror") || item2.Name.Contains("Glazing") || item2.Name == "WindowShell";
					Dictionary<(int, int, int), int> dictionary = new Dictionary<(int, int, int), int>();
					int[] array = new int[item2.Vertices.Count];
					for (int num = 0; num < item2.Vertices.Count; num++)
					{
						Point point = item2.Vertices[num];
						(int, int, int) key = ((int)Math.Round(point.X * 100000f), (int)Math.Round(point.Y * 100000f), (int)Math.Round(point.Z * 100000f));
						if (flag && dictionary.TryGetValue(key, out var value))
						{
							array[num] = value;
							continue;
						}
						value = list.Count;
						list.Add(new Vector3(point.X, point.Y, point.Z));
						array[num] = value;
						if (flag)
						{
							dictionary[key] = value;
						}
					}
					foreach (int triangle in item2.Triangles)
					{
						list2.Add(array[triangle]);
					}
				}
				Mesh val = new Mesh
				{
					name = "Vehicle_" + item.Key
				};
				meshes.Add(val);
				val.vertices = list.ToArray();
				val.triangles = list2.ToArray();
				val.RecalculateNormals();
				val.RecalculateBounds();
				if (twoSided)
				{
					Vector3[] normals = val.normals;
					int count = list.Count;
					list.AddRange(list.ToArray());
					List<Vector3> list3 = new List<Vector3>(normals);
					list3.AddRange(normals.Select((Vector3 p) => -p));
					int[] array2 = list2.ToArray();
					for (int num2 = 0; num2 < array2.Length; num2 += 3)
					{
						list2.AddRange(new int[3]
						{
							array2[num2] + count,
							array2[num2 + 2] + count,
							array2[num2 + 1] + count
						});
					}
					if (list.Count > 65535)
					{
						throw new InvalidOperationException("Puerta supera limite de vertices: " + item.Key);
					}
					val.vertices = list.ToArray();
					val.triangles = list2.ToArray();
					val.normals = list3.ToArray();
					val.RecalculateBounds();
				}
				GameObject val2 = new GameObject(((Object)val).name)
				{
					layer = layer
				};
				val2.transform.SetParent(root, false);
				val2.AddComponent<MeshFilter>().sharedMesh = val;
				((Renderer)val2.AddComponent<MeshRenderer>()).sharedMaterial = palette[item.Key];
			}
		}

		private void RegisterTree(VisualMount mount, Transform tree, Transform vehicleRoot)
		{
			if (Object.op_Implicit((Object)(object)tree) && !((Object)(object)tree == (Object)(object)vehicleRoot))
			{
				MeshRenderer[] componentsInChildren = ((Component)tree).GetComponentsInChildren<MeshRenderer>(true);
				foreach (MeshRenderer r in componentsInChildren)
				{
					Register(mount, (Renderer)(object)r);
				}
			}
		}

		private unsafe void MakeMirage(VehicleController v)
		{
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: 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_007b: 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_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_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: 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_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00f6: 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_0111: 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_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: 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_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: 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_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: 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_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: 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_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: 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_042a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0439: Unknown result type (might be due to invalid IL or missing references)
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			Transform val = null;
			try
			{
				val = Root("Ruta3_Mirage", ((Component)v).transform);
				((Component)val).gameObject.SetActive(false);
				if (Object.op_Implicit((Object)(object)v.FrontLeftWheel) && Object.op_Implicit((Object)(object)v.FrontRightWheel) && Object.op_Implicit((Object)(object)v.BackLeftWheel) && Object.op_Implicit((Object)(object)v.BackRightWheel))
				{
					Vector3 val2 = (((Component)v.FrontLeftWheel).transform.position + ((Component)v.FrontRightWheel).transform.position) * 0.5f;
					Vector3 val3 = (((Component)v.BackLeftWheel).transform.position + ((Component)v.BackRightWheel).transform.position) * 0.5f;
					Vector3 val4 = ((Component)v).transform.InverseTransformPoint(val2);
					Vector3 val5 = ((Component)v).transform.InverseTransformPoint(val3);
					float num = Mathf.Clamp(Vector3.Distance(((Component)v).transform.InverseTransformPoint(((Component)v.FrontLeftWheel).transform.position), ((Component)v).transform.InverseTransformPoint(((Component)v.FrontRightWheel).transform.position)) / 1.58f, 0.2f, 8f);
					float num2 = Mathf.Clamp(Vector3.Distance(val4, val5) / 2.4f, 0.2f, 8f);
					Vector3 val6 = val4 - val5;
					val6.y = 0f;
					val.localRotation = ((((Vector3)(ref val6)).sqrMagnitude > 0.001f) ? Quaternion.LookRotation(val6, Vector3.up) : Quaternion.identity);
					Transform obj = val;
					obj.localRotation *= Quaternion.Euler(0f, carYaw.Value, 0f);
					val.localScale = Vector3.Scale(new Vector3(num, num, num2), carScale.Value);
					val.localPosition = (val4 + val5) * 0.5f - Vector3.up * (0.34f * num * carScale.Value.y) + carOffset.Value;
					ManualLogSource logger = Logger;
					string[] obj2 = new string[8]
					{
						"Calibracion Mirage: posicion=",
						((object)val.localPosition/*cast due to .constrained prefix*/).ToString(),
						" escala=",
						((object)val.localScale/*cast due to .constrained prefix*/).ToString(),
						"; frente=",
						null,
						null,
						null
					};
					Vector3 val7 = val4;
					obj2[5] = ((object)(*(Vector3*)(&val7))/*cast due to .constrained prefix*/).ToString();
					obj2[6] = " atras=";
					val7 = val5;
					obj2[7] = ((object)(*(Vector3*)(&val7))/*cast due to .constrained prefix*/).ToString();
					logger.LogInfo((object)string.Concat(obj2));
				}
				else
				{
					val.localPosition = carOffset.Value;
					val.localScale = carScale.Value;
					val.localRotation = Quaternion.Euler(0f, carYaw.Value, 0f);
					Logger.LogWarning((object)"No se encontraron todas las ruedas; usando ajuste manual del Mirage.");
				}
				int layer = (Object.op_Implicit((Object)(object)v.mainBodyMesh) ? ((Component)v.mainBodyMesh).gameObject.layer : 0);
				List<Part>[] array = Factory.SplitMirageDoors(Factory.Mirage());
				Geometry(val, array[0], includeWheels: false, layer);
				int num3 = ((Object.op_Implicit((Object)(object)v.driverSideDoorTrigger) && val.InverseTransformPoint(((Component)v.driverSideDoorTrigger).transform.position).x > 0f) ? 1 : (-1));
				int[] array2 = new int[2] { -1, 1 };
				Vector3 val8 = default(Vector3);
				foreach (int num4 in array2)
				{
					((Vector3)(ref val8))..ctor((float)num4 * 0.76f, 0f, 0.69f);
					Transform transform = new GameObject((num4 < 0) ? "Mirage_LeftDoor" : "Mirage_RightDoor").transform;
					transform.SetParent(val, false);
					transform.localPosition = val8;
					List<Part> list = array[(num4 < 0) ? 1 : 2];
					foreach (Part item in list)
					{
						for (int j = 0; j < item.Vertices.Count; j++)
						{
							Point point = item.Vertices[j];
							item.Vertices[j] = new Point(point.X - val8.x, point.Y - val8.y, point.Z - val8.z);
						}
					}
					Geometry(transform, list, includeWheels: false, layer, twoSided: true);
					doors.Add(new DoorMotion
					{
						Pivot = transform,
						Side = num4,
						Trigger = ((num4 == num3) ? v.driverSideDoor : v.passengerSideDoor)
					});
				}
				VisualMount visualMount = new VisualMount
				{
					Root = val,
					Vehicle = v,
					Skin = ((Component)val).GetComponentsInChildren<Renderer>(true)
				};
				if (hideBody.Value)
				{
					Register(visualMount, (Renderer)(object)v.mainBodyMesh);
					Register(visualMount, (Renderer)(object)v.lod1Mesh);
					Register(visualMount, (Renderer)(object)v.lod2Mesh);
					if (Object.op_Implicit((Object)(object)v.driverSideDoor))
					{
						RegisterTree(visualMount, ((Component)v.driverSideDoor).transform, ((Component)v).transform);
					}
					if (Object.op_Implicit((Object)(object)v.passengerSideDoor))
					{
						RegisterTree(visualMount, ((Component)v.passengerSideDoor).transform, ((Component)v).transform);
					}
					if (Object.op_Implicit((Object)(object)v.carHoodAnimator))
					{
						RegisterTree(visualMount, ((Component)v.carHoodAnimator).transform, ((Component)v).transform);
					}
					if (Object.op_Implicit((Object)(object)v.backDoorContainer))
					{
						RegisterTree(visualMount, v.backDoorContainer.transform, ((Component)v).transform);
					}
					Renderer[] componentsInChildren = ((Component)v).GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val9 in componentsInChildren)
					{
						if ((val9 is MeshRenderer || val9 is SkinnedMeshRenderer) && !((Component)val9).transform.IsChildOf(val) && !((Object)(object)val9 == (Object)(object)v.leftWheelMesh) && !((Object)(object)val9 == (Object)(object)v.rightWheelMesh) && !((Object)(object)val9 == (Object)(object)v.backLeftWheelMesh) && !((Object)(object)val9 == (Object)(object)v.backRightWheelMesh) && (!Object.op_Implicit((Object)(object)v.destroyedTruckMesh) || !((Component)val9).transform.IsChildOf(v.destroyedTruckMesh.transform)) && !Object.op_Implicit((Object)(object)((Component)val9).GetComponentInParent<PlayerControllerB>()) && !Object.op_Implicit((Object)(object)((Component)val9).GetComponentInParent<GrabbableObject>()))
						{
							string text = ((Object)val9).name.ToLowerInvariant();
							if (!new string[6] { "steering", "dashboard", "seat", "radio", "gearstick", "button" }.Any(text.Contains))
							{
								Register(visualMount, val9);
							}
						}
					}
				}
				MeshRenderer[] array3 = (MeshRenderer[])(object)new MeshRenderer[4] { v.leftWheelMesh, v.rightWheelMesh, v.backLeftWheelMesh, v.backRightWheelMesh };
				foreach (MeshRenderer val10 in array3)
				{
					if (Object.op_Implicit((Object)(object)val10))
					{
						visualMount.Originals.Remove((Renderer)(object)val10);
					}
				}
				visuals.Add(visualMount);
				((Component)val).gameObject.SetActive(true);
				mounted.Add(((Component)v).transform);
				ApplyDefaultVisibility();
				Logger.LogInfo((object)("MONTAJE OK: Mirage 0.6.4; sin rotulos; piezas originales ocultas desde fuera=" + visualMount.Originals.Count));
				Logger.LogInfo((object)("Mallas originales Mirage: " + string.Join(", ", visualMount.Originals.Select((Renderer o) => ((Object)o).name))));
			}
			catch
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					roots.Remove(((Component)val).gameObject);
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				MeshRenderer[] array3 = (MeshRenderer[])(object)new MeshRenderer[3] { v.mainBodyMesh, v.lod1Mesh, v.lod2Mesh };
				foreach (MeshRenderer val11 in array3)
				{
					if (Object.op_Implicit((Object)(object)val11) && originals.TryGetValue((Renderer)(object)val11, out var value))
					{
						((Renderer)val11).forceRenderingOff = value;
						originals.Remove((Renderer)(object)val11);
					}
				}
				throw;
			}
		}

		private unsafe void MakeBus(Transform anchor, Collider inner)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_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)
			//IL_00a1: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: 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_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: 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_0259: 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_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02df: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0312: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_031b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: 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_0332: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_0354: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: 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_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e4: 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_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_051d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0522: Unknown result type (might be due to invalid IL or missing references)
			//IL_0529: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0534: Unknown result type (might be due to invalid IL or missing references)
			//IL_0539: Unknown result type (might be due to invalid IL or missing references)
			//IL_053e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0703: Unknown result type (might be due to invalid IL or missing references)
			//IL_0704: Unknown result type (might be due to invalid IL or missing references)
			Transform val = null;
			try
			{
				Vector3 val2 = busSize.Value;
				((Vector3)(ref val2))..ctor(Mathf.Clamp(val2.x, 3f, 20f), Mathf.Clamp(val2.y, 3f, 15f), Mathf.Clamp(val2.z, 6f, 35f));
				val = Root("Ruta3_Microbus", null);
				((Component)val).gameObject.SetActive(false);
				StartOfRound instance = StartOfRound.Instance;
				Bounds bounds = inner.bounds;
				Vector3 center = ((Bounds)(ref bounds)).center;
				Vector3 val3;
				if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.shipDoorNode))
				{
					bounds = inner.bounds;
					val3 = ((Bounds)(ref bounds)).center - anchor.forward;
				}
				else
				{
					val3 = instance.shipDoorNode.position;
				}
				Vector3 val4 = center - val3;
				val4.y = 0f;
				val.rotation = ((((Vector3)(ref val4)).sqrMagnitude > 0.01f) ? Quaternion.LookRotation(val4, Vector3.up) : anchor.rotation);
				Transform obj = val;
				obj.rotation *= Quaternion.Euler(0f, busYaw.Value, 0f);
				List<Vector3> list = new List<Vector3>();
				BoxCollider val5 = (BoxCollider)(object)((inner is BoxCollider) ? inner : null);
				int[] array = new int[2] { -1, 1 };
				Vector3 val6 = default(Vector3);
				foreach (int num in array)
				{
					int[] array2 = new int[2] { -1, 1 };
					foreach (int num2 in array2)
					{
						int[] array3 = new int[2] { -1, 1 };
						foreach (int num3 in array3)
						{
							((Vector3)(ref val6))..ctor((float)num, (float)num2, (float)num3);
							Vector3 item;
							if (!Object.op_Implicit((Object)(object)val5))
							{
								bounds = inner.bounds;
								Vector3 center2 = ((Bounds)(ref bounds)).center;
								bounds = inner.bounds;
								item = center2 + Vector3.Scale(((Bounds)(ref bounds)).extents, val6);
							}
							else
							{
								item = ((Component)val5).transform.TransformPoint(val5.center + Vector3.Scale(val5.size, val6) * 0.5f);
							}
							list.Add(item);
						}
					}
				}
				Vector3 val7 = Vector3.zero;
				foreach (Vector3 item2 in list)
				{
					Quaternion val8 = Quaternion.Inverse(val.rotation);
					bounds = inner.bounds;
					Vector3 val9 = val8 * (item2 - ((Bounds)(ref bounds)).center);
					val7 = Vector3.Max(val7, new Vector3(Mathf.Abs(val9.x), Mathf.Abs(val9.y), Mathf.Abs(val9.z)));
				}
				val2 = Vector3.Max(val2, new Vector3(val7.x * 2f + 0.7f, val7.y * 2f + 1.4f, val7.z * 2f + 1.6f));
				Transform obj2 = val;
				bounds = inner.bounds;
				obj2.position = ((Bounds)(ref bounds)).center - Vector3.up * (val7.y + 0.8f);
				Transform obj3 = val;
				obj3.position += val.rotation * busOffset.Value;
				val.localScale = new Vector3(val2.x / 2.1f, val2.y / 2.68f, val2.z / 6.5f);
				if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.shipDoorNode))
				{
					Vector3 forward = val.forward;
					float num4 = Vector3.Dot(instance.shipDoorNode.position - val.position, forward);
					Transform obj4 = val;
					obj4.position += forward * (num4 + 3.26f * val.localScale.z + 0.12f);
				}
				List<Part> source = Factory.Microbus();
				Geometry(val, source.Where((Part p) => !p.Name.StartsWith("RearDoor")).ToList(), includeWheels: true, 0);
				array = new int[2] { -1, 1 };
				foreach (int num5 in array)
				{
					string name = ((num5 < 0) ? "RearDoorLeft" : "RearDoorRight");
					Transform transform = new GameObject(name).transform;
					transform.SetParent(val, false);
					Geometry(transform, source.Where((Part p) => p.Name == name).ToList(), includeWheels: false, 0);
					doors.Add(new DoorMotion
					{
						Pivot = transform,
						Side = num5,
						Bus = true,
						Closed = Vector3.zero
					});
				}
				VisualMount visualMount = new VisualMount
				{
					Root = val,
					Follow = anchor,
					LocalPosition = anchor.InverseTransformPoint(val.position),
					LocalRotation = Quaternion.Inverse(anchor.rotation) * val.rotation,
					Interior = inner,
					Skin = ((Component)val).GetComponentsInChildren<Renderer>(true)
				};
				Transform val10 = anchor;
				while (Object.op_Implicit((Object)(object)val10.parent) && ((Object)val10).name != "HangarShip")
				{
					val10 = val10.parent;
				}
				if (((Object)val10).name == "HangarShip")
				{
					Renderer[] componentsInChildren = ((Component)val10).GetComponentsInChildren<Renderer>(true);
					foreach (Renderer val11 in componentsInChildren)
					{
						if ((val11 is MeshRenderer || val11 is SkinnedMeshRenderer) && !Object.op_Implicit((Object)(object)((Component)val11).GetComponentInParent<PlayerControllerB>()) && !Object.op_Implicit((Object)(object)((Component)val11).GetComponentInParent<GrabbableObject>()) && !Object.op_Implicit((Object)(object)((Component)val11).GetComponentInParent<VehicleController>()))
						{
							string text = ((Object)val11).name;
							Transform parent = ((Component)val11).transform.parent;
							while (Object.op_Implicit((Object)(object)parent) && (Object)(object)parent != (Object)(object)val10)
							{
								text = ((Object)parent).name + "/" + text;
								parent = parent.parent;
							}
							MeshFilter component = ((Component)val11).GetComponent<MeshFilter>();
							if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.sharedMesh))
							{
								text = text + "/" + ((Object)component.sharedMesh).name;
							}
							if (!ShipExteriorRules.KeepAccess(text))
							{
								Register(visualMount, val11);
							}
							else
							{
								Logger.LogInfo((object)("ACCESO EXTERIOR conservado: " + text));
							}
						}
					}
				}
				visuals.Add(visualMount);
				((Component)val).gameObject.SetActive(true);
				mounted.Add(anchor);
				ApplyDefaultVisibility();
				ManualLogSource logger = Logger;
				string[] obj5 = new string[5] { "MONTAJE OK: Microbus 0.6.4; ancla sin escala heredada; tamano=", null, null, null, null };
				Vector3 val12 = val2;
				obj5[1] = ((object)(*(Vector3*)(&val12))/*cast due to .constrained prefix*/).ToString();
				obj5[2] = "; hulls originales=";
				obj5[3] = visualMount.Originals.Count.ToString();
				obj5[4] = "; sin rotulos.";
				logger.LogInfo((object)string.Concat(obj5));
				Logger.LogInfo((object)("Mallas exteriores candidatas: " + string.Join(", ", visualMount.Originals.Select((Renderer o) => ((Object)o).name))));
			}
			catch
			{
				if (Object.op_Implicit((Object)(object)val))
				{
					roots.Remove(((Component)val).gameObject);
					Object.Destroy((Object)(object)((Component)val).gameObject);
				}
				throw;
			}
		}

		private void Shutdown()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Expected O, but got Unknown
			Logger.LogInfo((object)"Cierre de runtime Ruta3; retirando enganches.");
			SceneManager.sceneLoaded -= SceneLoaded;
			Application.quitting -= Shutdown;
			RenderPipelineManager.beginCameraRendering -= BeforeCamera;
			RenderPipelineManager.endCameraRendering -= AfterCamera;
			Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(BeforeLegacy));
			Camera.onPostRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPostRender, (Delegate?)new CameraCallback(AfterLegacy));
			if (Instance == this)
			{
				Instance = null;
			}
			Harmony obj = hooks;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			ResetCamera();
			foreach (GameObject root in roots)
			{
				if (Object.op_Implicit((Object)(object)root))
				{
					Object.Destroy((Object)(object)root);
				}
			}
			foreach (Material material in materials)
			{
				if (Object.op_Implicit((Object)(object)material))
				{
					Object.Destroy((Object)(object)material);
				}
			}
			foreach (Mesh mesh in meshes)
			{
				if (Object.op_Implicit((Object)(object)mesh))
				{
					Object.Destroy((Object)(object)mesh);
				}
			}
		}
	}
	internal static class ShipExteriorRules
	{
		public static bool KeepAccess(string path)
		{
			path = (path ?? string.Empty).ToLowerInvariant();
			string[] array = new string[7] { "catwalk", "rail", "ladder", "platform", "ramp", "stairs", "grating" };
			foreach (string value in array)
			{
				if (path.Contains(value))
				{
					return true;
				}
			}
			return false;
		}
	}
}
namespace Ruta3Company.Models
{
	public static class Factory
	{
		private static readonly float[][] RoofHeight;

		private static readonly float[][] RoofWidth;

		public static readonly Dictionary<string, string> Colors;

		private static void SurfaceBand(List<Part> parts, string name, string material, Func<float, float, Point> at, int steps = 24)
		{
			Part part = New(parts, name, material);
			for (int i = 0; i < steps; i++)
			{
				float arg = (float)i / (float)steps;
				float arg2 = (float)(i + 1) / (float)steps;
				Point point = at(arg, 0f);
				Point point2 = at(arg2, 0f);
				Point point3 = at(arg2, 1f);
				Point point4 = at(arg, 1f);
				Point point5 = Cross(Sub(point2, point), Sub(point3, point));
				if ((name == "HatchRoofLip") ? (point5.Y > 0f) : (point5.X * (point.X + point2.X + point3.X + point4.X) > 0f))
				{
					part.Quad(point, point2, point3, point4);
				}
				else
				{
					part.Quad(point4, point3, point2, point);
				}
			}
		}

		private static void FinishMirage(List<Part> parts)
		{
			int[] array = new int[2] { -1, 1 };
			foreach (int s in array)
			{
				SurfaceBand(parts, "PaintedCPillar", "aqua", delegate(float t, float v)
				{
					float z4 = -1.02f - t * 0.55f;
					Point result = SideGlass(s, 1f - v * 0.32f, z4);
					result.X += (float)s * 0.008f;
					result.Y += 0.005f;
					return result;
				});
				SurfaceBand(parts, "WindowLowerSeal", "rubber", delegate(float t, float v)
				{
					Point result = SideGlass(s, 0.035f + v * 0.035f, 0.72f - t * 2.19f);
					result.X += (float)s * 0.008f;
					return result;
				});
				Part part = New(parts, "FogRecessSurround", "aquaShade");
				Point[] ring = new Point[4]
				{
					P((float)s * 0.49f, 0.47f, 0f),
					P((float)s * 0.7f, 0.47f, 0f),
					P((float)s * 0.72f, 0.64f, 0f),
					P((float)s * 0.55f, 0.65f, 0f)
				};
				ParamCap(part, ring, (Point p) => P(p.X, p.Y, FrontZ(p.X, p.Y) + 0.009f), s < 0);
				for (int num = 0; num < 12; num++)
				{
					float z = -1.6f - (float)num * 0.22f / 12f;
					float z2 = -1.6f - (float)(num + 1) * 0.22f / 12f;
					Tube(parts, "HatchPanelGap", "aquaShade", CarTop(s, z, 0.78f, 0.009f), CarTop(s, z2, 0.78f, 0.009f), 0.0035f);
				}
				Disc(parts, "LampAmberInsert", "amber", CarTop(s, 1.56f, 0.92f, 0.023f), P((float)s * 0.2f, 1f, 0.15f), 0.025f);
				for (int num2 = 0; num2 < 5; num2++)
				{
					float z3 = 1.67f + (float)num2 * 0.032f;
					Tube(parts, "LensFluting", "chrome", CarTop(s, z3, 0.64f, 0.019f), CarTop(s, z3, 0.82f, 0.019f), 0.002f);
				}
				Tube(parts, "RearBumperReflector", "red", P((float)s * 0.5f, 0.48f, RearZ((float)s * 0.5f) - 0.01f), P((float)s * 0.64f, 0.48f, RearZ((float)s * 0.64f) - 0.01f), 0.012f);
			}
			SurfaceBand(parts, "HatchRoofLip", "aqua", delegate(float t, float v)
			{
				float num3 = -0.63f + t * 1.26f;
				return P(num3, 1.477f + 0.045f * (1f - num3 * num3 / 0.4f), -1.02f - v * 0.1f);
			});
			Tube(parts, "RearWiper", "black", P(-0.3f, 1.19f, -1.49f), P(0.23f, 1.2f, -1.48f), 0.007f);
			FrontPanel(parts, "FrontPlateMount", "rubber", 0f, 0.465f, 1.944f, 0.31f, 0.075f, 0.008f);
		}

		private static Point CoachSide(int s, float y, float z, float offset = 0.018f)
		{
			float num = Math.Max(0f, Math.Min(1f, (y - 1.3f) / 1.11f));
			return P((float)s * (CoachWidth(z) - num * 0.065f + offset), y, z);
		}

		private static void FinishCoach(List<Part> parts)
		{
			parts.RemoveAll((Part p) => p.Name == "ACSlat");
			for (int num = 0; num < 5; num++)
			{
				Tube(parts, "ACIntakeSlat", "rubber", P(-0.27f, 2.665f + (float)num * 0.017f, 0.453f), P(0.27f, 2.665f + (float)num * 0.017f, 0.453f), 0.004f);
			}
			int[] array = new int[2] { -1, 1 };
			float[] array2;
			foreach (int s in array)
			{
				for (int num3 = 0; num3 < 6; num3++)
				{
					float num4 = -2.94f + (float)num3 * 0.8f;
					Tube(parts, "SlidingWindowRail", "rubber", CoachSide(s, 1.83f, num4 + 0.05f), CoachSide(s, 1.83f, num4 + 0.75f), 0.009f);
					Tube(parts, "SlidingWindowDivider", "rubber", CoachSide(s, 1.83f, num4 + 0.4f), CoachSide(s, 2.38f, num4 + 0.4f), 0.01f);
					Tube(parts, "WindowLatch", "chrome", CoachSide(s, 1.92f, num4 + 0.43f, 0.023f), CoachSide(s, 2f, num4 + 0.43f, 0.023f), 0.007f);
				}
				for (int num5 = 0; num5 < 3; num5++)
				{
					int k = num5;
					SurfaceBand(parts, "FlamePaint", (num5 == 1) ? "purple" : "blue", delegate(float t, float v)
					{
						float z4 = -2.7f + (float)k * 0.62f + t * (3.8f - (float)k * 0.43f);
						float val = 0.91f + 0.18f * (float)Math.Sin(t * 3.5f + (float)k * 0.65f);
						float num10 = 0.13f * (1f - t) * (float)Math.Sin(Math.PI * (double)t) + 0.002f;
						float y = Math.Max(val, Arch(z4, 0.43f, 0.46f, 0.5f, 2.01f, -1.96f) + num10 * 0.5f + 0.025f) + (v - 0.5f) * num10;
						return CoachSide(s, y, z4, 0.024f + (float)k * 0.003f);
					}, 40);
				}
				Tube(parts, "LowerChromeMoulding", "chrome", CoachSide(s, 1.25f, -3.12f), CoachSide(s, 1.25f, 2.62f), 0.009f);
				array2 = new float[3] { -2.87f, 0.83f, 2.55f };
				foreach (float z in array2)
				{
					Disc(parts, "SideMarker", "amber", CoachSide(s, 0.61f, z, 0.025f), P(s, 0f, 0f), 0.027f);
				}
				array2 = new float[2] { 1.47f, -2.5f };
				foreach (float z2 in array2)
				{
					Box(parts, "MudFlap", "black", (float)s * 1.025f, 0.34f, z2, 0.22f, 0.28f, 0.035f);
				}
				int num7 = 0;
				while (s == 1 && num7 < 18)
				{
					float num8 = MathF.PI * (float)num7 / 18f;
					float num9 = MathF.PI * (float)(num7 + 1) / 18f;
					Tube(parts, "GuardArch", "chrome", P(0.55f * (float)Math.Cos(num8), 0.94f + 0.37f * (float)Math.Sin(num8), 3.44f), P(0.55f * (float)Math.Cos(num9), 0.94f + 0.37f * (float)Math.Sin(num9), 3.44f), 0.026f, wheel: false, 10);
					num7++;
				}
				Disc(parts, "GuardDrivingHousing", "black", P((float)s * 0.31f, 0.85f, 3.446f), P(0f, 0f, 1f), 0.085f);
				Disc(parts, "GuardDrivingLight", "lens", P((float)s * 0.31f, 0.85f, 3.453f), P(0f, 0f, 1f), 0.067f);
				Disc(parts, "RoofMarker", "amber", P((float)s * 0.77f, 2.49f, 2.975f), P(0f, 0f, 1f), 0.037f);
			}
			array2 = new float[2] { 0.94f, 1.64f };
			foreach (float z3 in array2)
			{
				Tube(parts, "PassengerDoorSeam", "rubber", CoachSide(1, Math.Max(0.48f, Arch(z3, 0.43f, 0.46f, 0.5f, 2.01f, -1.96f) + 0.02f), z3, 0.028f), CoachSide(1, 2.35f, z3, 0.028f), 0.007f);
			}
			Tube(parts, "PassengerDoorTop", "rubber", CoachSide(1, 2.35f, 0.94f, 0.028f), CoachSide(1, 2.35f, 1.64f, 0.028f), 0.007f);
			Tube(parts, "DoorGrabHandle", "chrome", CoachSide(1, 1.16f, 1.04f, 0.036f), CoachSide(1, 1.38f, 1.04f, 0.036f), 0.012f);
			RearCoachFacade(parts);
		}

		private static void RearCoachFacade(List<Part> parts)
		{
			int[] array = new int[2] { -1, 1 };
			foreach (int num in array)
			{
				Box(parts, "RearQuarterPanel", "white", (float)num * 0.73f, 1.4f, -3.205f, 0.53f, 1.96f, 0.065f);
				Box(parts, "RearQuarterGlassSeal", "rubber", (float)num * 0.724f, 1.83f, -3.244f, 0.425f, 0.92f, 0.012f);
				Box(parts, "RearQuarterGlass", "glass", (float)num * 0.724f, 1.83f, -3.253f, 0.379f, 0.865f, 0.008f);
				Box(parts, "RearBumperCorner", "rubber", (float)num * 0.73f, 0.48f, -3.25f, 0.55f, 0.115f, 0.13f);
				Box(parts, "RearBumperChrome", "chrome", (float)num * 0.73f, 0.51f, -3.32f, 0.48f, 0.025f, 0.016f);
				Tube(parts, "RearPortalSeal", "rubber", P((float)num * 0.458f, 0.42f, -3.248f), P((float)num * 0.458f, 2.08f, -3.248f), 0.012f);
				Tube(parts, "RearEntryGrab", "chrome", P((float)num * 0.5f, 0.92f, -3.29f), P((float)num * 0.5f, 1.49f, -3.29f), 0.016f);
				Box(parts, "RearLampHousing", "rubber", (float)num * 0.878f, 0.97f, -3.246f, 0.16f, 0.34f, 0.025f);
				Box(parts, "RearFacadeTailLight", "red", (float)num * 0.878f, 1.025f, -3.265f, 0.12f, 0.19f, 0.016f);
				Box(parts, "RearFacadeIndicator", "amber", (float)num * 0.878f, 0.895f, -3.266f, 0.12f, 0.055f, 0.017f);
				Box(parts, "RearFacadeReverse", "lens", (float)num * 0.878f, 0.846f, -3.266f, 0.12f, 0.035f, 0.017f);
			}
			Box(parts, "RearHeaderPanel", "white", 0f, 2.27f, -3.205f, 1.985f, 0.38f, 0.065f);
			Box(parts, "RearHeaderGlassSeal", "rubber", 0f, 2.285f, -3.244f, 1.78f, 0.235f, 0.012f);
			Box(parts, "RearHeaderGlass", "glass", 0f, 2.285f, -3.253f, 1.72f, 0.185f, 0.008f);
			Tube(parts, "RearPortalTopSeal", "rubber", P(-0.458f, 2.08f, -3.248f), P(0.458f, 2.08f, -3.248f), 0.012f);
			Tube(parts, "RearHighBrakeLight", "red", P(-0.16f, 2.43f, -3.252f), P(0.16f, 2.43f, -3.252f), 0.017f);
			parts.RemoveAll((Part p) => p.Name == "RearTailCluster" || p.Name == "RearReflector");
			array = new int[2] { -1, 1 };
			foreach (int num2 in array)
			{
				string name = ((num2 < 0) ? "RearDoorLeft" : "RearDoorRight");
				Box(parts, name, "white", (float)num2 * 0.225f, 1.25f, -3.26f, 0.444f, 1.65f, 0.045f);
				Box(parts, name, "rubber", (float)num2 * 0.225f, 1.65f, -3.289f, 0.36f, 0.69f, 0.012f);
				Box(parts, name, "glass", (float)num2 * 0.225f, 1.65f, -3.298f, 0.32f, 0.645f, 0.008f);
				Tube(parts, name, "chrome", P((float)num2 * 0.08f, 1.05f, -3.31f), P((float)num2 * 0.08f, 1.26f, -3.31f), 0.012f);
				Tube(parts, name, "blue", P((float)num2 * 0.04f, 0.75f, -3.29f), P((float)num2 * 0.41f, 0.86f, -3.29f), 0.024f);
			}
		}

		private static List<Point> ClipDoor(List<Point> polygon, Func<Point, float> plane, bool inside)
		{
			List<Point> list = new List<Point>();
			if (polygon.Count == 0)
			{
				return list;
			}
			Point point = polygon[polygon.Count - 1];
			float num = plane(point) * (float)(inside ? 1 : (-1));
			foreach (Point item in polygon)
			{
				float num2 = plane(item) * (float)(inside ? 1 : (-1));
				if (num >= 0f != num2 >= 0f)
				{
					list.Add(Add(point, Mul(Sub(item, point), num / (num - num2))));
				}
				if (num2 >= 0f)
				{
					list.Add(item);
				}
				point = item;
				num = num2;
			}
			return list;
		}

		private static void AddPolygon(Part part, List<Point> polygon)
		{
			for (int i = 1; i < polygon.Count - 1; i++)
			{
				Point point = polygon[0];
				Point point2 = polygon[i];
				Point point3 = polygon[i + 1];
				Point point4 = Cross(Sub(point2, point), Sub(point3, point));
				if (!(point4.X * point4.X + point4.Y * point4.Y + point4.Z * point4.Z < 1E-12f))
				{
					int count = part.Vertices.Count;
					part.Vertices.AddRange(new Point[3] { point, point2, point3 });
					part.Triangles.AddRange(new int[3]
					{
						count,
						count + 1,
						count + 2
					});
				}
			}
		}

		public static List<Part>[] SplitMirageDoors(List<Part> source)
		{
			List<Part>[] array = new List<Part>[3]
			{
				new List<Part>(),
				new List<Part>(),
				new List<Part>()
			};
			foreach (Part item in source)
			{
				Part[] array2 = new Part[3];
				for (int i = 0; i < 3; i++)
				{
					array2[i] = New(array[i], item.Name, item.Material, item.Wheel);
				}
				for (int j = 0; j < item.Triangles.Count; j += 3)
				{
					List<List<Point>> list = new List<List<Point>>
					{
						new List<Point>
						{
							item.Vertices[item.Triangles[j]],
							item.Vertices[item.Triangles[j + 1]],
							item.Vertices[item.Triangles[j + 2]]
						}
					};
					int[] array3 = new int[2] { -1, 1 };
					foreach (int side in array3)
					{
						List<List<Point>> list2 = new List<List<Point>>();
						foreach (List<Point> item2 in list)
						{
							List<Point> list3 = item2;
							Func<Point, float>[] array4 = new Func<Point, float>[5]
							{
								(Point p) => (float)side * p.X - 0.61f,
								(Point p) => p.Y - 0.43f,
								(Point p) => p.Z + 0.33f,
								(Point p) => 0.69f - p.Z,
								(Point p) => RoofY(p.Z) - 0.012f - p.Y
							};
							foreach (Func<Point, float> plane in array4)
							{
								List<Point> list4 = ClipDoor(list3, plane, inside: false);
								if (list4.Count > 2)
								{
									list2.Add(list4);
								}
								list3 = ClipDoor(list3, plane, inside: true);
								if (list3.Count < 3)
								{
									break;
								}
							}
							AddPolygon(array2[(side < 0) ? 1 : 2], list3);
						}
						list = list2;
					}
					foreach (List<Point> item3 in list)
					{
						AddPolygon(array2[0], item3);
					}
				}
			}
			List<Part>[] array5 = array;
			for (int k = 0; k < array5.Length; k++)
			{
				array5[k].RemoveAll((Part p) => p.Triangles.Count == 0);
			}
			return array;
		}

		static Factory()
		{
			RoofHeight = new float[7][]
			{
				new float[2] { 0.81f, 1.11f },
				new float[2] { 0.61f, 1.27f },
				new float[2] { 0.13f, 1.465f },
				new float[2] { -0.22f, 1.495f },
				new float[2] { -0.73f, 1.49f },
				new float[2] { -1.02f, 1.46f },
				new float[2] { -1.57f, 1.12f }
			};
			RoofWidth = new float[7][]
			{
				new float[2] { 0.81f, 0.737f },
				new float[2] { 0.61f, 0.705f },
				new float[2] { 0.13f, 0.64f },
				new float[2] { -0.22f, 0.65f },
				new float[2] { -0.73f, 0.65f },
				new float[2] { -1.02f, 0.64f },
				new float[2] { -1.57f, 0.68f }
			};
			Colors = new Dictionary<string, string>
			{
				{ "aqua", "#08acc5" },
				{ "white", "#e5e6e4" },
				{ "blue", "#263ab6" },
				{ "purple", "#793ab0" },
				{ "glass", "#233e49" },
				{ "chrome", "#aebac5" },
				{ "black", "#171d23" },
				{ "cyan", "#24f4ff" },
				{ "pink", "#ff3d9b" },
				{ "red", "#cc2948" },
				{ "lamp", "#fff3bd" }
			};
			Colors["lens"] = "#bcd3de";
			Colors["rubber"] = "#303c43";
			Colors["amber"] = "#f4ac33";
			Colors["aquaShade"] = "#0794ad";
		}

		private static Point Add(Point a, Point b)
		{
			return P(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
		}

		private static Point Mul(Point a, float s)
		{
			return P(a.X * s, a.Y * s, a.Z * s);
		}

		private static Point Sub(Point a, Point b)
		{
			return Add(a, Mul(b, -1f));
		}

		private static Point Cross(Point a, Point b)
		{
			return P(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
		}

		private static Point Unit(Point a)
		{
			float num = (float)Math.Sqrt(a.X * a.X + a.Y * a.Y + a.Z * a.Z);
			return Mul(a, 1f / num);
		}

		private static float Curve(float z, float[][] values)
		{
			if (z >= values[0][0])
			{
				return values[0][1];
			}
			for (int i = 0; i < values.Length - 1; i++)
			{
				if (z >= values[i + 1][0])
				{
					float num = (values[i][0] - z) / (values[i][0] - values[i + 1][0]);
					num = num * num * (3f - 2f * num);
					return values[i][1] * (1f - num) + values[i + 1][1] * num;
				}
			}
			return values[^1][1];
		}

		private static void Loft(List<Part> parts, string name, string material, List<Point[]> rings, bool openBack = false)
		{
			Part part = New(parts, name, material);
			part.Cap(rings[0], reverse: false);
			for (int i = 0; i < rings.Count - 1; i++)
			{
				for (int j = 0; j < rings[i].Length; j++)
				{
					int num = (j + 1) % rings[i].Length;
					part.Quad(rings[i][j], rings[i + 1][j], rings[i + 1][num], rings[i][num]);
				}
			}
			if (!openBack)
			{
				part.Cap(rings[rings.Count - 1], reverse: true);
			}
		}

		private static void Tube(List<Part> parts, string name, string material, Point a, Point b, float radius, bool wheel = false, int segments = 8)
		{
			Point point = Unit(Sub(b, a));
			Point a2 = point;
			Point point2 = Unit(Cross(b: (Math.Abs(a2.Y) < 0.9f) ? P(0f, 1f, 0f) : P(1f, 0f, 0f), a: a2));
			Point a3 = Cross(point, point2);
			Part part = New(parts, name, material, wheel);
			Point[] array = new Point[segments];
			Point[] array2 = new Point[segments];
			for (int i = 0; i < segments; i++)
			{
				double num = (double)(i * 2) * Math.PI / (double)segments;
				Point b2 = Add(Mul(point2, radius * (float)Math.Cos(num)), Mul(a3, radius * (float)Math.Sin(num)));
				array[i] = Add(a, b2);
				array2[i] = Add(b, b2);
			}
			for (int j = 0; j < segments; j++)
			{
				int num2 = (j + 1) % segments;
				part.Quad(array[j], array[num2], array2[num2], array2[j]);
			}
			part.Cap(array, reverse: true);
			part.Cap(array2, reverse: false);
		}

		private static void Disc(List<Part> parts, string name, string mat, Point center, Point normal, float radius, bool wheel = false, int segments = 20)
		{
			Point point = Unit(normal);
			Point a = point;
			Point point2 = Unit(Cross(b: (Math.Abs(a.Y) < 0.9f) ? P(0f, 1f, 0f) : P(1f, 0f, 0f), a: a));
			Point a2 = Cross(point, point2);
			Point[] array = new Point[segments];
			for (int i = 0; i < segments; i++)
			{
				double num = (double)i * Math.PI * 2.0 / (double)segments;
				array[i] = Add(center, Add(Mul(point2, radius * (float)Math.Cos(num)), Mul(a2, radius * (float)Math.Sin(num))));
			}
			New(parts, name, mat, wheel).Cap(array, reverse: false);
		}

		private static void FrontPanel(List<Part> parts, string name, string material, float x, float y, float z, float w, float h, float corner)
		{
			List<Point> list = new List<Point>();
			float[][] array = new float[4][]
			{
				new float[3] { 1f, 1f, 0f },
				new float[3] { -1f, 1f, 90f },
				new float[3] { -1f, -1f, 180f },
				new float[3] { 1f, -1f, 270f }
			};
			foreach (float[] array2 in array)
			{
				for (int j = 0; j < 4; j++)
				{
					double num = (double)(array2[2] + (float)(j * 30)) * Math.PI / 180.0;
					list.Add(P(x + array2[0] * (w / 2f - corner) + corner * (float)Math.Cos(num), y + array2[1] * (h / 2f - corner) + corner * (float)Math.Sin(num), z));
				}
			}
			New(parts, name, material).Cap(list.ToArray(), reverse: false);
		}

		private static void DetailedWheel(List<Part> parts, float x, float y, float z, float radius, float width, bool coach)
		{
			int num = ((x > 0f) ? 1 : (-1));
			Part part = New(parts, "RoundedTire", "black", wheel: true);
			float[] array = new float[4]
			{
				(0f - width) / 2f,
				(0f - width) * 0.36f,
				width * 0.36f,
				width / 2f
			};
			float[] array2 = new float[4]
			{
				radius * 0.84f,
				radius,
				radius,
				radius * 0.84f
			};
			for (int i = 0; i < array.Length - 1; i++)
			{
				for (int j = 0; j < 32; j++)
				{
					double num2 = (double)(j * 2) * Math.PI / 32.0;
					double num3 = (double)((j + 1) * 2) * Math.PI / 32.0;
					part.Quad(P(x + array[i], y + array2[i] * (float)Math.Cos(num2), z + array2[i] * (float)Math.Sin(num2)), P(x + array[i], y + array2[i] * (float)Math.Cos(num3), z + array2[i] * (float)Math.Sin(num3)), P(x + array[i + 1], y + array2[i + 1] * (float)Math.Cos(num3), z + array2[i + 1] * (float)Math.Sin(num3)), P(x + array[i + 1], y + array2[i + 1] * (float)Math.Cos(num2), z + array2[i + 1] * (float)Math.Sin(num2)));
				}
			}
			float num4 = x + (float)num * (width / 2f + 0.003f);
			Disc(parts, "TireSidewall", "black", P(num4, y, z), P(num, 0f, 0f), radius * 0.845f, wheel: true, 32);
			Disc(parts, "RimBarrel", "rubber", P(num4 + (float)num * 0.002f, y, z), P(num, 0f, 0f), radius * 0.64f, wheel: true, 32);
			Part part2 = New(parts, "PolishedRim", "chrome", wheel: true);
			for (int k = 0; k < 32; k++)
			{
				double num5 = (double)k * Math.PI / 16.0;
				double num6 = (double)(k + 1) * Math.PI / 16.0;
				float num7 = radius * 0.66f;
				float num8 = radius * 0.59f;
				float x2 = num4 + (float)num * 0.007f;
				Point[] array3 = new Point[4]
				{
					P(x2, y + num8 * (float)Math.Cos(num5), z + num8 * (float)Math.Sin(num5)),
					P(x2, y + num7 * (float)Math.Cos(num5), z + num7 * (float)Math.Sin(num5)),
					P(x2, y + num7 * (float)Math.Cos(num6), z + num7 * (float)Math.Sin(num6)),
					P(x2, y + num8 * (float)Math.Cos(num6), z + num8 * (float)Math.Sin(num6))
				};
				if (num > 0)
				{
					part2.Quad(array3[0], array3[1], array3[2], array3[3]);
				}
				else
				{
					part2.Quad(array3[3], array3[2], array3[1], array3[0]);
				}
			}
			int num9 = (coach ? 8 : 7);
			Part part3 = New(parts, "AlloySpokes", "chrome", wheel: true);
			for (int l = 0; l < num9; l++)
			{
				double num10 = (double)(l * 2) * Math.PI / (double)num9;
				float num11 = radius * 0.13f;
				float num12 = radius * 0.6f;
				float x3 = num4 + (float)num * 0.01f;
				Point[] array4 = new Point[4]
				{
					P(x3, y + num11 * (float)Math.Cos(num10 - 0.2), z + num11 * (float)Math.Sin(num10 - 0.2)),
					P(x3, y + num12 * (float)Math.Cos(num10 - 0.105), z + num12 * (float)Math.Sin(num10 - 0.105)),
					P(x3, y + num12 * (float)Math.Cos(num10 + 0.105), z + num12 * (float)Math.Sin(num10 + 0.105)),
					P(x3, y + num11 * (float)Math.Cos(num10 + 0.2), z + num11 * (float)Math.Sin(num10 + 0.2))
				};
				if (num > 0)
				{
					part3.Quad(array4[0], array4[1], array4[2], array4[3]);
				}
				else
				{
					part3.Quad(array4[3], array4[2], array4[1], array4[0]);
				}
			}
			Disc(parts, "HubCap", "chrome", P(num4 + (float)num * 0.014f, y, z), P(num, 0f, 0f), radius * 0.16f, wheel: true, 16);
		}

		private static float Arch(float z, float floor, float centerY, float radius, float front, float back)
		{
			float num = Math.Min(Math.Abs(z - front), Math.Abs(z - back));
			if (!(num < radius))
			{
				return floor;
			}
			return Math.Max(floor, centerY + (float)Math.Sqrt(radius * radius - num * num));
		}

		private static float CarWidth(float z)
		{
			return Curve(z, new float[7][]
			{
				new float[2] { 1.91f, 0.68f },
				new float[2] { 1.64f, 0.8f },
				new float[2] { 1.2f, 0.845f },
				new float[2] { 0f, 0.835f },
				new float[2] { -1.2f, 0.84f },
				new float[2] { -1.66f, 0.79f },
				new float[2] { -1.86f, 0.71f }
			});
		}

		private static float CarBelt(float z)
		{
			return Curve(z, new float[6][]
			{
				new float[2] { 1.91f, 0.87f },
				new float[2] { 1.6f, 0.98f },
				new float[2] { 0.73f, 1.09f },
				new float[2] { -0.8f, 1.09f },
				new float[2] { -1.55f, 1.05f },
				new float[2] { -1.86f, 0.96f }
			});
		}

		private static Point CarSide(int s, float y, float z)
		{
			return P((float)s * (CarWidth(z) + 0.008f), y, z);
		}

		private static Point CarTop(int side, float z, float f, float offset)
		{
			return WarpCar(P((float)side * CarWidth(z) * f, TopY(z, f) + offset, z));
		}

		private static void CurvedLamp(List<Part> parts, int side)
		{
			float[][] array = new float[6][]
			{
				new float[2] { 1.88f, 0.42f },
				new float[2] { 1.89f, 0.78f },
				new float[2] { 1.76f, 0.96f },
				new float[2] { 1.49f, 0.98f },
				new float[2] { 1.55f, 0.77f },
				new float[2] { 1.72f, 0.6f }
			};
			float centerZ = 0f;
			float centerF = 0f;
			float[][] array2 = array;
			foreach (float[] array3 in array2)
			{
				centerZ += array3[0] / (float)array.Length;
				centerF += array3[1] / (float)array.Length;
			}
			for (int layer = 0; layer < 2; layer++)
			{
				Part part = New(parts, (layer == 0) ? "LampPerimeter" : "SweptHeadlamp", (layer == 0) ? "chrome" : "lens");
				for (int j = 0; j < array.Length; j++)
				{
					float[] a = array[j];
					float[] b = array[(j + 1) % array.Length];
					Func<float, float, Point> func = delegate(float u, float v)
					{
						float num6 = centerZ + u * (a[0] - centerZ) + v * (b[0] - centerZ);
						float num7 = centerF + u * (a[1] - centerF) + v * (b[1] - centerF);
						if (layer == 0)
						{
							num6 = centerZ + (num6 - centerZ) * 1.035f;
							num7 = centerF + (num7 - centerF) * 1.035f;
						}
						return CarTop(side, num6, num7, (layer == 0) ? 0.008f : 0.013f);
					};
					Action<Point, Point, Point> action = delegate(Point p, Point q, Point r)
					{
						int count = part.Vertices.Count;
						part.Vertices.AddRange(new Point[3] { p, q, r });
						bool flag = Cross(Sub(q, p), Sub(r, p)).Y > 0f;
						part.Triangles.AddRange((!flag) ? new int[3]
						{
							count,
							count + 2,
							count + 1
						} : new int[3]
						{
							count,
							count + 1,
							count + 2
						});
					};
					for (int num = 0; num < 6; num++)
					{
						for (int num2 = 0; num2 < 6 - num; num2++)
						{
							float num3 = (float)num / 6f;
							float num4 = (float)num2 / 6f;
							float num5 = 1f / 6f;
							action(func(num3, num4), func(num3 + num5, num4), func(num3, num4 + num5));
							if (num + num2 < 5)
							{
								action(func(num3 + num5, num4), func(num3 + num5, num4 + num5), func(num3, num4 + num5));
							}
						}
					}
				}
			}
		}

		public static List<Part> Mirage()
		{
			List<Part> list = new List<Part>();
			List<Point[]> list2 = new List<Point[]>();
			for (int i = 0; i <= 80; i++)
			{
				float num = 1.91f - (float)i * 0.047125f;
				float num2 = CarWidth(num);
				float num3 = CarBelt(num);
				float num4 = Arch(num, 0.39f, 0.34f, 0.385f, 1.2f, -1.2f);
				float num5 = num3 + ((num > 0.72f) ? 0.018f : 0.025f);
				list2.Add(new Point[13]
				{
					P((0f - num2) * 0.79f, 0.36f, num),
					P(num2 * 0.79f, 0.36f, num),
					P(num2 * 0.98f, num4, num),
					P(num2, Math.Max(num4 + 0.05f, num3 - 0.15f), num),
					P(num2 * 0.965f, num3 - 0.035f, num),
					P(num2 * 0.88f, num3, num),
					P(num2 * 0.45f, num5, num),
					P(0f, num5 + 0.012f, num),
					P((0f - num2) * 0.45f, num5, num),
					P((0f - num2) * 0.88f, num3, num),
					P((0f - num2) * 0.965f, num3 - 0.035f, num),
					P(0f - num2, Math.Max(num4 + 0.05f, num3 - 0.15f), num),
					P((0f - num2) * 0.98f, num4, num)
				});
			}
			Loft(list, "RoundedAquaBody", "aqua", list2);
			Hull(list, "CabinGlazing", "glass", new float[6][]
			{
				new float[5] { 0.79f, 0.765f, 1.075f, 0.735f, 1.115f },
				new float[5] { 0.59f, 0.785f, 1.075f, 0.705f, 1.25f },
				new float[5] { 0.13f, 0.785f, 1.075f, 0.64f, 1.495f },
				new float[5] { -0.47f, 0.785f, 1.075f, 0.645f, 1.52f },
				new float[5] { -1.01f, 0.775f, 1.075f, 0.64f, 1.495f },
				new float[5] { -1.57f, 0.725f, 1.045f, 0.675f, 1.15f }
			});
			List<Point[]> list3 = new List<Point[]>();
			float[][] array = new float[4][]
			{
				new float[3] { 0.15f, 0.635f, 1.495f },
				new float[3] { -0.15f, 0.65f, 1.54f },
				new float[3] { -0.7f, 0.65f, 1.54f },
				new float[3] { -1.03f, 0.635f, 1.495f }
			};
			foreach (float[] obj in array)
			{
				float z = obj[0];
				float num6 = obj[1];
				float num7 = obj[2];
				list3.Add(new Point[7]
				{
					P(0f - num6, num7 - 0.012f, z),
					P(num6, num7 - 0.012f, z),
					P(num6, num7 + 0.015f, z),
					P(num6 * 0.72f, num7 + 0.042f, z),
					P(0f, num7 + 0.055f, z),
					P((0f - num6) * 0.72f, num7 + 0.042f, z),
					P(0f - num6, num7 + 0.015f, z)
				});
			}
			Loft(list, "CurvedHatchRoof", "aqua", list3);
			int[] array2 = new int[2] { -1, 1 };
			foreach (int num8 in array2)
			{
				Tube(list, "APillar", "aqua", P((float)num8 * 0.77f, 1.083f, 0.79f), P((float)num8 * 0.65f, 1.5f, 0.13f), 0.029f);
				Tube(list, "RearPillar", "aqua", P((float)num8 * 0.65f, 1.5f, -1.01f), P((float)num8 * 0.735f, 1.07f, -1.57f), 0.035f);
				Tube(list, "BPillar", "black", P((float)num8 * 0.79f, 1.09f, -0.33f), P((float)num8 * 0.654f, 1.525f, -0.33f), 0.027f);
				Tube(list, "WindowSill", "rubber", P((float)num8 * 0.792f, 1.087f, 0.72f), P((float)num8 * 0.788f, 1.087f, -1.34f), 0.013f);
				Tube(list, "RoofGutter", "aquaShade", P((float)num8 * 0.643f, 1.506f, 0.13f), P((float)num8 * 0.643f, 1.506f, -1.01f), 0.011f);
				float[] array3 = new float[2] { -0.32f, -1.49f };
				foreach (float z2 in array3)
				{
					Tube(list, "DoorSeam", "aquaShade", CarSide(num8, Math.Max(0.45f, Arch(z2, 0.39f, 0.34f, 0.385f, 1.2f, -1.2f) + 0.03f), z2), CarSide(num8, 1.055f, z2), 0.004f);
				}
				array3 = new float[2] { -0.16f, -1.09f };
				foreach (float num9 in array3)
				{
					Tube(list, "HandleRecess", "aquaShade", CarSide(num8, 1.005f, num9 - 0.095f), CarSide(num8, 1.005f, num9 + 0.095f), 0.022f);
					Tube(list, "SatinDoorHandle", "chrome", CarSide(num8, 1.01f, num9 - 0.075f), CarSide(num8, 1.01f, num9 + 0.075f), 0.012f);
				}
				Tube(list, "MirrorStem", "black", P((float)num8 * 0.775f, 1.14f, 0.61f), P((float)num8 * 0.91f, 1.17f, 0.61f), 0.023f);
				Hull(list, "RoundedMirror", "aqua", new float[3][]
				{
					new float[5] { 0.74f, 0.035f, 1.105f, 0.03f, 1.2f },
					new float[5] { 0.68f, 0.105f, 1.09f, 0.09f, 1.23f },
					new float[5] { 0.5f, 0.09f, 1.1f, 0.08f, 1.21f }
				});
				Part part = list[list.Count - 1];
				for (int l = 0; l < part.Vertices.Count; l++)
				{
					Point value = part.Vertices[l];
					value.X += (float)num8 * 0.93f;
					part.Vertices[l] = value;
				}
				Disc(list, "MirrorGlass", "chrome", P((float)num8 * 0.93f, 1.16f, 0.496f), P(0f, 0f, -1f), 0.065f);
				array3 = new float[2] { 1.2f, -1.2f };
				foreach (float num10 in array3)
				{
					DetailedWheel(list, (float)num8 * 0.79f, 0.34f, num10, 0.34f, 0.2f, coach: false);
					for (int m = 0; m < 16; m++)
					{
						double num11 = (double)m * Math.PI / 16.0;
						double num12 = (double)(m + 1) * Math.PI / 16.0;
						float z3 = num10 + 0.385f * (float)Math.Cos(num11);
						float z4 = num10 + 0.385f * (float)Math.Cos(num12);
						Tube(list, "FenderLip", "aquaShade", P((float)num8 * (CarWidth(z3) + 0.014f), 0.34f + 0.385f * (float)Math.Sin(num11), z3), P((float)num8 * (CarWidth(z4) + 0.014f), 0.34f + 0.385f * (float)Math.Sin(num12), z4), 0.009f);
					}
				}
				CurvedLamp(list, num8);
				Disc(list, "FogLampSocket", "black", P((float)num8 * 0.61f, 0.56f, 1.91f), P(0f, 0f, 1f), 0.074f);
				Disc(list, "FogLampRing", "chrome", P((float)num8 * 0.61f, 0.56f, 1.914f), P(0f, 0f, 1f), 0.057f);
				Disc(list, "FogLampLens", "lens", P((float)num8 * 0.61f, 0.56f, 1.918f), P(0f, 0f, 1f), 0.046f);
				Box(list, "RearLamp", "red", (float)num8 * 0.686f, 0.985f, -1.838f, 0.115f, 0.255f, 0.055f);
				Box(list, "RearReverseLamp", "lens", (float)num8 * 0.687f, 0.955f, -1.869f, 0.088f, 0.047f, 0.009f);
				Tube(list, "SillContour", "aquaShade", CarSide(num8, 0.41f, 0.75f), CarSide(num8, 0.41f, -0.75f), 0.015f);
			}
			FrontPanel(list, "LowerIntakeRim", "aquaShade", 0f, 0.6f, 1.926f, 1.09f, 0.265f, 0.065f);
			FrontPanel(list, "LowerIntake", "black", 0f, 0.6f, 1.93f, 1.01f, 0.215f, 0.055f);
			for (int n = 0; n < 4; n++)
			{
				Tube(list, "GrilleSlat", "rubber", P(-0.46f, 0.533f + (float)n * 0.044f, 1.934f), P(0.46f, 0.533f + (float)n * 0.044f, 1.934f), 0.006f);
			}
			FrontPanel(list, "UpperIntake", "black", 0f, 0.855f, 1.933f, 0.43f, 0.039f, 0.012f);
			array2 = new int[2] { -1, 1 };
			foreach (int num13 in array2)
			{
				Tube(list, "Wiper", "black", P((float)num13 * 0.1f, 1.12f, 0.8f), P((float)num13 * 0.5f, 1.155f, 0.735f), 0.008f);
			}
			Box(list, "RearLicensePlate", "white", 0f, 0.69f, -1.872f, 0.33f, 0.105f, 0.012f);
			Tube(list, "RearHatchTrim", "chrome", P(-0.25f, 0.87f, -1.872f), P(0.25f, 0.87f, -1.872f), 0.01f);
			UpgradeMirage(list);
			FinishMirage(list);
			return list;
		}

		public static List<Part> Microbus()
		{
			List<Part> list = new List<Part>();
			List<Point[]> list2 = new List<Point[]>();
			for (int i = 0; i <= 100; i++)
			{
				float z = 3.22f - (float)i * 6.42f / 100f;
				float num = Curve(z, new float[5][]
				{
					new float[2] { 3.22f, 0.89f },
					new float[2] { 2.94f, 0.99f },
					new float[2] { 2.6f, 1.045f },
					new float[2] { -2.96f, 1.04f },
					new float[2] { -3.2f, 0.995f }
				});
				float y = Arch(z, 0.43f, 0.46f, 0.5f, 2.01f, -1.96f);
				list2.Add(new Point[8]
				{
					P((0f - num) * 0.9f, 0.42f, z),
					P(num * 0.9f, 0.42f, z),
					P(num, y, z),
					P(num, 1.13f, z),
					P(num * 0.99f, 1.245f, z),
					P((0f - num) * 0.99f, 1.245f, z),
					P(0f - num, 1.13f, z),
					P(0f - num, y, z)
				});
			}
			Loft(list, "LowerBusBody", "white", list2, openBack: true);
			Hull(list, "WindowShell", "glass", new float[4][]
			{
				new float[5] { 3.22f, 0.89f, 1.245f, 0.87f, 1.72f },
				new float[5] { 2.94f, 0.99f, 1.245f, 0.93f, 2.18f },
				new float[5] { 2.62f, 1.04f, 1.245f, 0.975f, 2.41f },
				new float[5] { -3.2f, 0.995f, 1.245f, 0.96f, 2.41f }
			}, openBack: true);
			List<Point[]> list3 = new List<Point[]>();
			float[][] array = new float[4][]
			{
				new float[3] { 2.66f, 0.97f, 2.41f },
				new float[3] { 2.3f, 0.99f, 2.48f },
				new float[3] { -2.85f, 0.98f, 2.48f },
				new float[3] { -3.2f, 0.95f, 2.43f }
			};
			foreach (float[] obj in array)
			{
				float z2 = obj[0];
				float num2 = obj[1];
				float num3 = obj[2];
				list3.Add(new Point[9]
				{
					P(0f - num2, num3 - 0.01f, z2),
					P(num2, num3 - 0.01f, z2),
					P(num2, num3 + 0.035f, z2),
					P(num2 * 0.83f, num3 + 0.12f, z2),
					P(num2 * 0.45f, num3 + 0.18f, z2),
					P(0f, num3 + 0.2f, z2),
					P((0f - num2) * 0.45f, num3 + 0.18f, z2),
					P((0f - num2) * 0.83f, num3 + 0.12f, z2),
					P(0f - num2, num3 + 0.035f, z2)
				});
			}
			Loft(list, "Roof", "white", list3, openBack: true);
			int[] array2 = new int[2] { -1, 1 };
			float[] array3;
			foreach (int num4 in array2)
			{
				for (int k = 0; k < 7; k++)
				{
					float z3 = -2.94f + (float)k * 0.8f;
					Tube(list, "WindowRubber", "rubber", P((float)num4 * 1.046f, 1.25f, z3), P((float)num4 * 0.98f, 2.42f, z3), 0.043f);
					Tube(list, "WindowPillar", "white", P((float)num4 * 1.051f, 1.25f, z3), P((float)num4 * 0.985f, 2.42f, z3), 0.025f);
				}
				array3 = new float[2] { 1.25f, 2.4f };
				foreach (float num5 in array3)
				{
					Tube(list, "WindowBeltSeal", "rubber", P((float)num4 * ((num5 > 2f) ? 0.981f : 1.049f), num5, -3.16f), P((float)num4 * ((num5 > 2f) ? 0.981f : 1.049f), num5, 2.55f), 0.014f);
				}
				Tube(list, "CyanRoofStrip", "cyan", P((float)num4 * 1.004f, 2.43f, -3.15f), P((float)num4 * 1.004f, 2.43f, 2.6f), 0.014f);
				Tube(list, "CyanSillStrip", "cyan", P((float)num4 * 1.052f, 0.445f, -3.1f), P((float)num4 * 1.052f, 0.445f, 2.55f), 0.014f);
				Tube(list, "MirrorMount", "chrome", P((float)num4 * 0.99f, 1.78f, 2.87f), P((float)num4 * 1.3f, 1.78f, 2.87f), 0.018f);
				Box(list, "MirrorHousing", "black", (float)num4 * 1.3f, 1.72f, 2.85f, 0.13f, 0.31f, 0.1f);
				Box(list, "MirrorReflector", "chrome", (float)num4 * 1.3f, 1.72f, 2.79f, 0.1f, 0.26f, 0.009f);
				array3 = new float[2] { 2.01f, -1.96f };
				foreach (float num6 in array3)
				{
					DetailedWheel(list, (float)num4 * 1.03f, 0.46f, num6, 0.46f, 0.24f, coach: true);
					for (int m = 0; m < 16; m++)
					{
						double num7 = (double)m * Math.PI / 16.0;
						double num8 = (double)(m + 1) * Math.PI / 16.0;
						Tube(list, "WheelArchSeal", "rubber", P((float)num4 * 1.058f, 0.46f + 0.505f * (float)Math.Sin(num7), num6 + 0.505f * (float)Math.Cos(num7)), P((float)num4 * 1.058f, 0.46f + 0.505f * (float)Math.Sin(num8), num6 + 0.505f * (float)Math.Cos(num8)), 0.012f);
					}
				}
				float[][] array4 = new float[7][]
				{
					new float[2] { -3.12f, 0.83f },
					new float[2] { -2.55f, 1.03f },
					new float[2] { -1.55f, 0.97f },
					new float[2] { -0.5f, 0.68f },
					new float[2] { 0.65f, 0.72f },
					new float[2] { 1.55f, 1.03f },
					new float[2] { 2.6f, 1.15f }
				};
				for (int n = 0; n < 2; n++)
				{
					Part part = New(list, "FlowingLivery", (n == 0) ? "blue" : "purple");
					for (int num9 = 0; num9 < array4.Length - 1; num9++)
					{
						float x = (float)num4 * (1.067f + (float)n * 0.003f);
						float z4 = array4[num9][0];
						float z5 = array4[num9 + 1][0];
						float num10 = array4[num9][1] - (float)n * 0.2f;
						float num11 = array4[num9 + 1][1] - (float)n * 0.2f;
						float num12 = ((n == 0) ? 0.16f : 0.1f);
						Point[] array5 = new Point[4]
						{
							P(x, num10 - num12, z4),
							P(x, num11 - num12, z5),
							P(x, num11, z5),
							P(x, num10, z4)
						};
						if (num4 < 0)
						{
							part.Quad(array5[0], array5[1], array5[2], array5[3]);
						}
						else
						{
							part.Quad(array5[3], array5[2], array5[1], array5[0]);
						}
					}
				}
				Box(list, "RearTailCluster", "red", (float)num4 * 0.88f, 0.97f, -3.216f, 0.13f, 0.3f, 0.022f);
				Box(list, "RearReflector", "amber", (float)num4 * 0.88f, 0.83f, -3.231f, 0.11f, 0.035f, 0.01f);
			}
			FrontPanel(list, "FrontIntakeFrame", "chrome", 0f, 0.84f, 3.241f, 1.04f, 0.41f, 0.055f);
			FrontPanel(list, "FrontIntake", "black", 0f, 0.84f, 3.247f, 0.95f, 0.34f, 0.04f);
			for (int num13 = 0; num13 < 5; num13++)
			{
				Tube(list, "IntakeSlat", "rubber", P(-0.45f, 0.71f + (float)num13 * 0.06f, 3.25f), P(0.45f, 0.71f + (float)num13 * 0.06f, 3.25f), 0.009f);
			}
			array2 = new int[2] { -1, 1 };
			foreach (int num14 in array2)
			{
				FrontPanel(list, "HeadlampHousing", "black", (float)num14 * 0.69f, 0.9f, 3.249f, 0.43f, 0.24f, 0.035f);
				array3 = new float[2] { 0.58f, 0.78f };
				foreach (float num15 in array3)
				{
					Disc(list, "RoundCoachHeadlamp", "lens", P((float)num14 * num15, 0.9f, 3.254f), P(0f, 0f, 1f), 0.078f);
				}
				Disc(list, "CoachIndicator", "amber", P((float)num14 * 0.91f, 1.12f, 3.23f), P(0f, 0f, 1f), 0.045f);
				Tube(list, "FrontPinkStrip", "pink", P((float)num14 * 0.5f, 1.16f, 3.24f), P((float)num14 * 0.86f, 1.16f, 3.24f), 0.012f);
				Tube(list, "FrontWiper", "black", P((float)num14 * 0.08f, 1.43f, 3.17f), P((float)num14 * 0.62f, 1.58f, 3.12f), 0.011f);
				Tube(list, "WindshieldPillar", "white", P((float)num14 * 0.9f, 1.3f, 3.23f), P((float)num14 * 0.974f, 2.41f, 2.62f), 0.034f);
			}
			Tube(list, "WindshieldDivision", "rubber", P(0f, 1.26f, 3.236f), P(0f, 2.39f, 2.665f), 0.013f);
			for (int num16 = 0; num16 < 3; num16++)
			{
				float y2 = 0.54f + (float)num16 * 0.26f;
				Tube(list, "ChromeGuard", "chrome", P(-1.02f, y2, 3.4f), P(1.02f, y2, 3.4f), 0.032f, wheel: false, 12);
				array2 = new int[2] { -1, 1 };
				foreach (int num17 in array2)
				{
					Tube(list, "GuardReturn", "chrome", P((float)num17 * 1.02f, y2, 3.4f), P((float)num17 * 1.09f, y2, 3.29f), 0.032f, wheel: false, 12);
				}
			}
			array3 = new float[2] { -0.87f, 0.87f };
			foreach (float x2 in array3)
			{
				Tube(list, "GuardUpright", "chrome", P(x2, 0.44f, 3.4f), P(x2, 1.17f, 3.4f), 0.033f, wheel: false, 12);
			}
			Tube(list, "PinkFrontSill", "pink", P(-1f, 0.42f, 3.36f), P(1f, 0.42f, 3.36f), 0.014f);
			for (int num18 = 0; num18 < 3; num18++)
			{
				Box(list, "RoofVent", "rubber", 0f, 2.69f, 1.5f - (float)num18 * 1.55f, 0.58f, 0.045f, 0.38f);
			}
			Box(list, "EntryStep", "rubber", 1.09f, 0.4f, 1.28f, 0.18f, 0.07f, 0.68f);
			UpgradeCoach(list);
			FinishCoach(list);
			return list;
		}

		private static float FrontZ(float x, float y)
		{
			return 1.91f - 0.14f * (x / 0.7f) * (x / 0.7f) + 0.012f * (1f - (y - 0.62f) * (y - 0.62f) / 0.09f);
		}

		private static float RearZ(float x)
		{
			return -1.86f + 0.1f * (x / 0.73f) * (x / 0.73f);
		}

		private static Point WarpCar(Point p)
		{
			if (p.Z > 1.48f)
			{
				float num = (p.Z - 1.48f) / 0.43f;
				num = num * num * (3f - 2f * num);
				p.Z += (FrontZ(p.X, p.Y) - 1.91f) * num;
			}
			else if (p.Z < -1.5f)
			{
				float num2 = (0f - p.Z - 1.5f) / 0.36f;
				num2 = num2 * num2 * (3f - 2f * num2);
				p.Z += (RearZ(p.X) + 1.86f) * num2;
			}
			return p;
		}

		private static float TopY(float z, float f)
		{
			return CarBelt(z) + ((z > 0.72f) ? 0.018f : 0.025f) + 0.012f - 0.03f * f * f - 0.09f * (float)Math.Pow(f, 10.0);
		}

		private static void ParamCap(Part part, Point[] ring, Func<Point, Point> map, bool reverse)
		{
			Point center = P(0f, 0f, 0f);
			foreach (Point a in ring)
			{
				center = Add(center, Mul(a, 1f / (float)ring.Length));
			}
			foreach (int item in Enumerable.Range(0, ring.Length))
			{
				Point a2 = ring[item];
				Point b = ring[(item + 1) % ring.Length];
				Func<float, float, Point> func = (float u, float v) => map(Add(center, Add(Mul(Sub(a2, center), u), Mul(Sub(b, center), v))));
				Action<Point, Point, Point> action = delegate(Point p, Point q, Point r)
				{
					int count = part.Vertices.Count;
					part.Vertices.AddRange(new Point[3] { p, q, r });
					part.Triangles.AddRange((!reverse) ? new int[3]
					{
						count,
						count + 1,
						count + 2
					} : new int[3]
					{
						count,
						count + 2,
						count + 1
					});
				};
				for (int num = 0; num < 7; num++)
				{
					for (int num2 = 0; num2 < 7 - num; num2++)
					{
						float num3 = (float)num / 7f;
						float num4 = (float)num2 / 7f;
						float num5 = 1f / 7f;
						action(func(num3, num4), func(num3 + num5, num4), func(num3, num4 + num5));
						if (num + num2 < 6)
						{
							action(func(num3 + num5, num4), func(num3 + num5, num4 + num5), func(num3, num4 + num5));
						}
					}
				}
			}
		}

		private static void WarpedLoft(List<Part> parts, string name, string material, List<Point[]> rings, Func<Point, Point> map, bool openBack = false)
		{
			Part part = New(parts, name, material);
			for (int i = 0; i < rings.Count - 1; i++)
			{
				for (int j = 0; j < rings[i].Length; j++)
				{
					int num = (j + 1) % rings[i].Length;
					part.Quad(map(rings[i][j]), map(rings[i + 1][j]), map(rings[i + 1][num]), map(rings[i][num]));
				}
			}
			ParamCap(part, rings[0], map, reverse: false);
			if (!openBack)
			{
				ParamCap(part, rings[rings.Count - 1], map, reverse: true);
			}
		}

		private static float Profile(float z, float[][] points)
		{
			if (z >= points[0][0])
			{
				return points[0][1];
			}
			for (int i = 0; i < points.Length - 1; i++)
			{
				if (z >= points[i + 1][0])
				{
					int num = Math.Max(0, i - 1);
					int num2 = Math.Min(points.Length - 1, i + 2);
					float num3 = points[i + 1][0] - points[i][0];
					float num4 = (z - points[i][0]) / num3;
					float num5 = (points[i + 1][1] - points[num][1]) / (points[i + 1][0] - points[num][0]);
					float num6 = (points[num2][1] - points[i][1]) / (points[num2][0] - points[i][0]);
					float val = (2f * num4 * num4 * num4 - 3f * num4 * num4 + 1f) * points[i][1] + (num4 * num4 * num4 - 2f * num4 * num4 + num4) * num3 * num5 + (-2f * num4 * num4 * num4 + 3f * num4 * num4) * points[i + 1][1] + (num4 * num4 * num4 - num4 * num4) * num3 * num6;
					return Math.Max(Math.Min(points[i][1], points[i + 1][1]), Math.Min(Math.Max(points[i][1], points[i + 1][1]), val));
				}
			}
			return points[^1][1];
		}

		private static float RoofY(float z)
		{
			return Profile(z, RoofHeight);
		}

		private static float RoofW(float z)
		{
			return Profile(z, RoofWidth);
		}

		private static Point SideGlass(int side, float t, float z)
		{
			float num = Curve(z, new float[4][]
			{
				new float[2] { 0.81f, 0.77f },
				new float[2] { 0.3f, 0.785f },
				new float[2] { -1f, 0.78f },
				new float[2] { -1.57f, 0.735f }
			});
			float num2 = 1.02f;
			float num3 = RoofY(z);
			float num4 = RoofW(z);
			float num5 = num + (num4 - num) * t + 0.012f * (float)Math.Sin((double)t * Math.PI);
			return P((float)side * num5, num2 + (num3 - num2) * t, z);
		}

		private static void NewCarShell(List<Part> parts)
		{
			List<Point[]> list = new List<Point[]>();
			for (int i = 0; i <= 100; i++)
			{
				float z = 1.91f - (float)i * 3.77f / 100f;
				float num = CarWidth(z);
				float num2 = Arch(z, 0.39f, 0.34f, 0.385f, 1.2f, -1.2f);
				float num3 = TopY(z, 1f);
				List<Point> list2 = new List<Point>
				{
					P((0f - num) * 0.78f, 0.36f, z),
					P(num * 0.78f, 0.36f, z),
					P(num * 0.98f, num2, z),
					P(num * 1.001f, (num2 + num3) * 0.5f, z)
				};
				float[] array = new float[19]
				{
					1f, 0.97f, 0.93f, 0.87f, 0.78f, 0.66f, 0.52f, 0.34f, 0.16f, 0f,
					-0.16f, -0.34f, -0.52f, -0.66f, -0.78f, -0.87f, -0.93f, -0.97f, -1f
				};
				foreach (float num4 in array)
				{
					list2.Add(P(num * num4, TopY(z, Math.Abs(num4)), z));
				}
				list2.Add(P((0f - num) * 1.001f, (num2 + num3) * 0.5f, z));
				list2.Add(P((0f - num) * 0.98f, num2, z));
				list.Add(list2.ToArray());
			}
			WarpedLoft(parts, "RoundedAquaBody", "aqua", list, WarpCar);
			List<Point[]> list3 = new List<Point[]>();
			for (int k = 0; k <= 70; k++)
			{
				float z2 = 0.81f - (float)k * 2.38f / 70f;
				List<Point> list4 = new List<Point>();
				list4.Add(SideGlass(-1, 0f, z2));
				list4.Add(SideGlass(1, 0f, z2));
				float[] array = new float[5] { 0.12f, 0.35f, 0.6f, 0.82f, 1f };
				foreach (float t in array)
				{
					list4.Add(SideGlass(1, t, z2));
				}
				float num5 = RoofW(z2);
				float num6 = RoofY(z2);
				array = new float[7] { 0.8f, 0.6f, 0.35f, 0f, -0.35f, -0.6f, -0.8f };
				foreach (float num7 in array)
				{
					list4.Add(P(num5 * num7, num6 + 0.055f * (1f - num7 * num7), z2));
				}
				array = new float[5] { 1f, 0.82f, 0.6f, 0.35f, 0.12f };
				foreach (float t2 in array)
				{
					list4.Add(SideGlass(-1, t2, z2));
				}
				list3.Add(list4.ToArray());
			}
			Loft(parts, "CabinGlazing", "glass", list3);
			Part part = New(parts, "BubbleRoofBody", "aqua");
			for (int l = 0; l < 50; l++)
			{
				for (int m = 0; m < 28; m++)
				{
					float arg = 0.14f - (float)l * 1.17f / 50f;
					float arg2 = 0.14f - (float)(l + 1) * 1.17f / 50f;
					float arg3 = -1f + (float)m * 2f / 28f;
					float arg4 = -1f + (float)(m + 1) * 2f / 28f;
					Func<float, float, Point> func = (float s, float z3) => P(RoofW(z3) * s, RoofY(z3) + 0.055f * (1f - s * s) + 0.009f, z3);
					part.Quad(func(arg3, arg), func(arg4, arg), func(arg4, arg2), func(arg3, arg2));
				}
			}
		}

		private static void CurvedPillars(List<Part> parts, int side)
		{
			float[][] array = new float[2][]
			{
				new float[2] { 0.81f, 0.14f },
				new float[2] { -1.02f, -1.57f }
			};
			foreach (float[] array2 in array)
			{
				for (int j = 0; j < 12; j++)
				{
					float z = array2[0] + (array2[1] - array2[0]) * (float)j / 12f;
					float z2 = array2[0] + (array2[1] - array2[0]) * (float)(j + 1) / 12f;
					Point a = SideGlass(side, 1f, z);
					Point b = SideGlass(side, 1f, z2);
					a.Y += 0.006f;
					b.Y += 0.006f;
					Tube(parts, "CurvedPillar", "aqua", a, b, 0.024f, wheel: false, 10);
				}
			}
			for (int k = 0; k < 8; k++)
			{
				Point a2 = SideGlass(side, (float)k / 8f, -0.33f);
				Point b2 = SideGlass(side, (float)(k + 1) / 8f, -0.33f);
				a2.X += (float)side * 0.006f;
				b2.X += (float)side * 0.006f;
				Tube(parts, "BPillar", "black", a2, b2, 0.023f);
			}
			float[] array3 = new float[2] { 0.14f, -1.03f };
			foreach (float z3 in array3)
			{
				for (int l = 0; l < 22; l++)
				{
					float num = -1f + (float)l * 2f / 22f;
					float num2 = -1f + (float)(l + 1) * 2f / 22f;
					Tube(parts, "RoofSeal", "rubber", P(RoofW(z3) * num, RoofY(z3) + 0.055f * (1f - num * num) + 0.013f, z3), P(RoofW(z3) * num2, RoofY(z3) + 0.055f * (1f - num2 * num2) + 0.013f, z3), 0.004f);
				}
			}
			for (int m = 0; m < 20; m++)
			{
				float z4 = 0.75f + (float)m * 0.88f / 20f;
				float z5 = 0.75f + (float)(m + 1) * 0.88f / 20f;
				Tube(parts, "HoodPanelGap", "aquaShade", CarTop(side, z4, 0.83f, 0.007f), CarTop(side, z5, 0.83f, 0.007f), 0.003f);
			}
		}

		private static void UpgradeMirage(List<Part> parts)
		{
			HashSet<string> replaced = new HashSet<string>
			{
				"RoundedAquaBody", "CabinGlazing", "CurvedHatchRoof", "APillar", "RearPillar", "BPillar", "RoofGutter", "Wiper", "GrilleSlat", "RearLamp",
				"RearReverseLamp"
			};
			parts.RemoveAll((Part p) => replaced.Contains(p.Name));
			NewCarShell(parts);
			int[] array = new int[2] { -1, 1 };
			foreach (int side in array)
			{
				CurvedPillars(parts, side);
				Tube(parts, "Wiper", "black", CarTop(side, 0.76f, 0.12f, 0.01f), CarTop(side, 0.7f, 0.63f, 0.012f), 0.007f);
			}
			HashSet<string> hashSet = new HashSet<string> { "LowerIntakeRim", "LowerIntake", "GrilleSlat", "UpperIntake", "FogLampSocket", "FogLampRing", "FogLampLens" };
			foreach (Part part in parts)
			{
				if (hashSet.Contains(part.Name))
				{
					Func<Point, Point> func = delegate(Point p)
					{
						p.Z = FrontZ(p.X, p.Y) + (p.Z - 1.91f) + (part.Name.StartsWith("Fog") ? 0.015f : 0f);
						return p;
					};
					if (part.Name == "LowerIntakeRim" || part.Name == "LowerIntake" || part.Name == "UpperIntake")
					{
						Point[] ring = part.Vertices.Skip(1).ToArray();
						part.Vertices.Clear();
						part.Triangles.Clear();
						ParamCap(part, ring, func, reverse: false);
					}
					else
					{
						for (int num2 = 0; num2 < part.Vertices.Count; num2++)
						{
							part.Vertices[num2] = func(part.Vertices[num2]);
						}
					}
				}
				if (part.Name == "RearLamp" || part.Name == "RearReverseLamp")
				{
					for (int num3 = 0; num3 < part.Vertices.Count; num3++)
					{
						Point value = part.Vertices[num3];
						float num4 = ((part.Name == "RearLamp") ? (-1.838f) : (-1.869f));
						value.Z = RearZ(value.X) - 0.015f + (value.Z - num4) + ((part.Name == "RearReverseLamp") ? (-0.028f) : 0f);
						part.Vertices[num3] = value;
					}
				}
			}
			for (int num5 = 0; num5 < 4; nu