Decompiled source of Cruiser Enhancement v1.1.2

Cruiser_Enhancement.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalNetworkAPI;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;

[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("Cruiser_Enhancement")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+68be25e1ee34373b7232fbe2f7cd71593e34f110")]
[assembly: AssemblyProduct("Cruiser_Enhancement")]
[assembly: AssemblyTitle("Cruiser_Enhancement")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 Cruiser_Enhancement
{
	public static class CruiserEnhancement
	{
		[Serializable]
		private struct CruiserSyncData
		{
			public ulong vehicleNetworkId;

			public float motorTorque;

			public int gear;

			public float engineRPM;

			public float posX;

			public float posY;

			public float posZ;

			public float rotX;

			public float rotY;

			public float rotZ;

			public float rotW;

			public float velX;

			public float velY;

			public float velZ;

			public float steeringInput;

			public float steeringWheelAnimFloat;
		}

		[Serializable]
		private struct MagnetSyncData
		{
			public ulong vehicleNetworkId;

			public float posX;

			public float posY;

			public float posZ;

			public float rotX;

			public float rotY;

			public float rotZ;

			public bool magnetedToShip;
		}

		private class VehicleSyncState
		{
			public Vector3 targetPosition;

			public Quaternion targetRotation;

			public Vector3 predictedVelocity;

			public Vector3 angularVelocity;

			public Vector3 smoothedPosition;

			public Quaternion smoothedRotation;

			public Vector3 smoothDampVelocity;

			public float lastReceiveTime;

			public Vector3 lastReceivedPosition;

			public bool initialized;

			public float syncedMotorTorque;

			public float lastMotorTorqueUpdateTime;

			public float syncedSteeringInput;

			public float syncedSteeringWheelAnimFloat;

			public bool usesLethalNetworkAPI;
		}

		[CompilerGenerated]
		private sealed class <SendMagnetStateDelayed>d__201 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public VehicleController vehicle;

			public ulong clientId;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SendMagnetStateDelayed>d__201(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0048: Expected O, but got Unknown
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0083: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_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_00ec: 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_0106: Unknown result type (might be due to invalid IL or missing references)
				//IL_0115: Unknown result type (might be due to invalid IL or missing references)
				//IL_0128: Unknown result type (might be due to invalid IL or missing references)
				//IL_013b: 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)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(1.5f);
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					if ((Object)vehicle == (Object)null || !vehicle.magnetedToShip)
					{
						return false;
					}
					if (!networkMessageInitialized || magnetSyncMessage == null)
					{
						ManualLogSource logger = CruiserEnhancement.logger;
						if (logger != null)
						{
							logger.LogWarning((object)"[Cruiser] LethalNetworkAPI not ready — can't send magnet state");
						}
						return false;
					}
					Vector3 val = Vector3.zero;
					Quaternion val2 = Quaternion.identity;
					if (magnetTargetPositionField != null)
					{
						val = (Vector3)magnetTargetPositionField.GetValue(vehicle);
					}
					if (magnetTargetRotationField != null)
					{
						val2 = (Quaternion)magnetTargetRotationField.GetValue(vehicle);
					}
					MagnetSyncData magnetSyncData = default(MagnetSyncData);
					magnetSyncData.vehicleNetworkId = ((NetworkBehaviour)vehicle).NetworkObjectId;
					magnetSyncData.posX = val.x;
					magnetSyncData.posY = val.y;
					magnetSyncData.posZ = val.z;
					magnetSyncData.rotX = ((Quaternion)(ref val2)).eulerAngles.x;
					magnetSyncData.rotY = ((Quaternion)(ref val2)).eulerAngles.y;
					magnetSyncData.rotZ = ((Quaternion)(ref val2)).eulerAngles.z;
					magnetSyncData.magnetedToShip = true;
					MagnetSyncData magnetSyncData2 = magnetSyncData;
					magnetSyncMessage.SendClient(magnetSyncData2, clientId);
					return false;
				}
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		public static ManualLogSource logger;

		private static Harmony harmony;

		private static bool isCruiserImprovedLoaded = false;

		private const string CRUISER_IMPROVED_GUID = "DiggC.CruiserImproved";

		public static float cameraBackDistance = 10f;

		public static float cameraUpDistance = 4f;

		public static float cameraLookAhead = 2f;

		public static float cameraSmoothSpeed = 4f;

		public static float STEERING_MULTIPLIER = 2.1f;

		private const float STEERING_DEAD_ZONE = 0.05f;

		private static float smoothedThrottle = 0f;

		private static float smoothedReverse = 0f;

		private const float THROTTLE_RAMP_UP_PER_SEC = 14f;

		private const float THROTTLE_RAMP_DOWN_PER_SEC = 10f;

		private const float REVERSE_RAMP_UP_PER_SEC = 6f;

		private const float REVERSE_RAMP_DOWN_PER_SEC = 8f;

		private const float HILL_THROTTLE_BOOST = 0.38f;

		private const float HILL_DRIVE_BLEND_MAX = 1.28f;

		private const float HILL_FORWARD_ACCEL = 26f;

		private const float HILL_ASSIST_SPEED_HEADROOM = 0.92f;

		private const float HILL_ASSIST_HEADROOM_WINDOW = 0.38f;

		private const float BRAKE_DELAY_FLAT = 0.4f;

		private const float BRAKE_DELAY_UPHILL = 0.72f;

		public static float MaxThrottleInputCap = 1f;

		public static float MaxReverseInputCap = 0.42f;

		public static float UphillAssistMultiplier = 0.6f;

		public static bool IgnitionEasyModeEnabled = true;

		public static float CruiserDamageMultiplier = 0.55f;

		public static bool SoftCruiserCollisionDamage = true;

		public static bool PlayerInvincibleInCruiser = false;

		public static float MAX_FORWARD_SPEED = 12f;

		public static float MAX_REVERSE_SPEED = 10f;

		private const int VANILLA_CRUISER_ID = 0;

		private const float CRUISER_MASS = 275f;

		private const float CRUISER_DRAG = 0.055f;

		private const float CRUISER_ANGULAR_DRAG = 1.35f;

		private static HashSet<int> physicsModifiedCruisers = new HashSet<int>();

		private static float idleTimer = 0f;

		private static bool isBraking = false;

		private static float lastHapticTime = 0f;

		private const float HAPTIC_COOLDOWN = 0.05f;

		private static float currentHapticLow = 0f;

		private static float currentHapticHigh = 0f;

		private static bool wasInVehicle = false;

		private static Camera tpCamera;

		private static VehicleController currentVehicle;

		private static VehicleController lastKnownVehicle;

		private static bool isThirdPerson = false;

		private static Vector3 currentCameraPos;

		private static Vector3 cameraVelocity;

		private static bool wasIgnitionStarted = false;

		private static bool wasLocalPlayerInControl = false;

		private static bool wasLocalPlayerInPassenger = false;

		private static bool tipsUpdated = false;

		private static bool pendingHudUpdate = false;

		private static float hudUpdateTimer = 0f;

		private const float HUD_UPDATE_DELAY = 0.15f;

		private static bool lastInputWasController = false;

		private static Camera originalMainCamera;

		private static int cameraRetryCount = 0;

		private const int MAX_CAMERA_RETRY = 5;

		private static float cameraVerifyTimer = 0f;

		private const float CAMERA_VERIFY_INTERVAL = 0.1f;

		private static float boostHapticTimer = 0f;

		private static bool isBoostHapticActive = false;

		private static Dictionary<int, VehicleSyncState> vehicleSyncStates = new Dictionary<int, VehicleSyncState>();

		private static LNetworkMessage<CruiserSyncData> cruiserSyncMessage;

		private static LNetworkMessage<MagnetSyncData> magnetSyncMessage;

		private static bool networkMessageInitialized = false;

		private static float lastSyncSendTime = 0f;

		private const float SYNC_SEND_INTERVAL = 0.01f;

		private const float SYNC_SMOOTH_TIME = 0.06f;

		private const float SYNC_ROT_SPEED = 25f;

		private const float SYNC_SNAP_DISTANCE = 20f;

		private const float SYNC_PREDICTION_FACTOR = 0.7f;

		private const float SYNC_MAX_PREDICTION_TIME = 0.15f;

		private const float SYNC_MIN_VELOCITY = 0.5f;

		private static FieldInfo syncSpeedMultiplierField;

		private static FieldInfo syncedPositionField;

		private static FieldInfo syncedRotationField;

		private static FieldInfo mainRigidbodyField;

		private static FieldInfo magnetedToShipField;

		private static FieldInfo testingVehicleInEditorField;

		private static FieldInfo hasBeenSpawnedField;

		private static FieldInfo itemShipField;

		private static FieldInfo ragdollPhysicsBodyField;

		private static FieldInfo windwiperPhysicsBody1Field;

		private static FieldInfo windwiperPhysicsBody2Field;

		private static FieldInfo windwiper1Field;

		private static FieldInfo windwiper2Field;

		private static FieldInfo averageCountField;

		private static FieldInfo movingAverageLengthField;

		private static FieldInfo averageVelocityField;

		private static FieldInfo stabilityField;

		private static FieldInfo magnetStartPositionField;

		private static FieldInfo magnetTargetPositionField;

		private static FieldInfo magnetStartRotationField;

		private static FieldInfo magnetTargetRotationField;

		private static FieldInfo magnetPositionCurveField;

		private static FieldInfo magnetRotationCurveField;

		private static FieldInfo magnetTimeField;

		private static FieldInfo magnetRotationTimeField;

		private static FieldInfo averageVelocityAtMagnetStartField;

		private static FieldInfo finishedMagnetingField;

		private static FieldInfo syncRotationSpeedField;

		private static FieldInfo truckVelocityLastFrameField;

		private static FieldInfo syncCruiserPositionIntervalField;

		private static FieldInfo moveInputVectorField;

		private static FieldInfo steeringWheelAnimFloatField;

		private static MethodInfo syncCruiserPhysicsMethod;

		private static MethodInfo driverExitLocalMethod;

		private static FieldInfo chanceToStartIgnitionField;

		private static bool reflectionInitialized = false;

		private static Vector3 visualVehiclePosition;

		private static Quaternion visualVehicleRotation;

		private static Vector3 visualVelocity;

		private static bool visualInterpolationInitialized = false;

		private const float VISUAL_SMOOTH_TIME = 0.08f;

		private const float VISUAL_ROT_SPEED = 20f;

		private const float POSITION_SNAP_THRESHOLD = 15f;

		private static readonly FieldInfo cruiserTooltipsField = typeof(VehicleController).GetField("carTooltips", BindingFlags.Instance | BindingFlags.NonPublic);

		private static float savedMotorTorqueLeft = 0f;

		private static float savedMotorTorqueRight = 0f;

		private static bool motorTorqueOverridden = false;

		private static float lastVehicleSpeed = 0f;

		private static bool pendingHornCheck = false;

		private static float hornCheckTimer = 0f;

		private const float HORN_CHECK_DELAY = 0.2f;

		private const float HORN_CHECK_DURATION = 0.5f;

		private static bool pendingIgnitionSwitch = false;

		private static float ignitionSwitchTimer = 0f;

		private const float IGNITION_SWITCH_DELAY = 0.3f;

		private static bool pendingPassengerExit = false;

		private static float passengerExitTimer = 0f;

		private static VehicleController pendingExitVehicle = null;

		private const float PASSENGER_EXIT_DELAY = 0.4f;

		public static bool IsThirdPersonEnabled => isThirdPerson;

		private static void InitializeNetworkMessages()
		{
			if (networkMessageInitialized)
			{
				return;
			}
			try
			{
				cruiserSyncMessage = LNetworkMessage<CruiserSyncData>.Create("Cruiser_Enhancement_CruiserSync", (Action<CruiserSyncData, ulong>)null, (Action<CruiserSyncData>)OnCruiserSyncReceived, (Action<CruiserSyncData, ulong>)OnCruiserSyncReceivedFromClient);
				Action<MagnetSyncData> action = OnMagnetSyncReceived;
				magnetSyncMessage = LNetworkMessage<MagnetSyncData>.Create("Cruiser_Enhancement_MagnetSync", (Action<MagnetSyncData, ulong>)OnMagnetSyncRequestReceived, action, (Action<MagnetSyncData, ulong>)null);
				networkMessageInitialized = true;
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] LethalNetworkAPI didn't init — " + ex.Message));
				}
			}
		}

		private static void OnMagnetSyncReceived(MagnetSyncData data)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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)
			try
			{
				if ((Object)NetworkManager.Singleton == (Object)null)
				{
					return;
				}
				VehicleController[] array = Object.FindObjectsOfType<VehicleController>();
				Vector3 val = default(Vector3);
				VehicleController[] array2 = array;
				foreach (VehicleController val2 in array2)
				{
					if (((NetworkBehaviour)val2).NetworkObjectId == data.vehicleNetworkId)
					{
						((Vector3)(ref val))..ctor(data.posX, data.posY, data.posZ);
						Quaternion val3 = Quaternion.Euler(data.rotX, data.rotY, data.rotZ);
						if (magnetTargetPositionField != null)
						{
							magnetTargetPositionField.SetValue(val2, val);
						}
						if (magnetTargetRotationField != null)
						{
							magnetTargetRotationField.SetValue(val2, val3);
						}
						break;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogWarning((object)("[Cruiser] Magnet sync hiccup (incoming): " + ex.Message));
				}
			}
		}

		private static void OnMagnetSyncRequestReceived(MagnetSyncData data, ulong clientId)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameNetworkManager instance = GameNetworkManager.Instance;
				if ((Object)(object)instance == (Object)null || !instance.isHostingGame)
				{
					return;
				}
				VehicleController val = StartOfRound.Instance?.attachedVehicle;
				if (!((Object)val == (Object)null) && val.magnetedToShip)
				{
					Vector3 val2 = Vector3.zero;
					Quaternion val3 = Quaternion.identity;
					if (magnetTargetPositionField != null)
					{
						val2 = (Vector3)magnetTargetPositionField.GetValue(val);
					}
					if (magnetTargetRotationField != null)
					{
						val3 = (Quaternion)magnetTargetRotationField.GetValue(val);
					}
					MagnetSyncData magnetSyncData = default(MagnetSyncData);
					magnetSyncData.vehicleNetworkId = ((NetworkBehaviour)val).NetworkObjectId;
					magnetSyncData.posX = val2.x;
					magnetSyncData.posY = val2.y;
					magnetSyncData.posZ = val2.z;
					magnetSyncData.rotX = ((Quaternion)(ref val3)).eulerAngles.x;
					magnetSyncData.rotY = ((Quaternion)(ref val3)).eulerAngles.y;
					magnetSyncData.rotZ = ((Quaternion)(ref val3)).eulerAngles.z;
					magnetSyncData.magnetedToShip = true;
					MagnetSyncData magnetSyncData2 = magnetSyncData;
					magnetSyncMessage.SendClient(magnetSyncData2, clientId);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogWarning((object)("[Cruiser] Magnet sync hiccup (handling request): " + ex.Message));
				}
			}
		}

		private static void RequestMagnetSync(VehicleController vehicle)
		{
			if (!networkMessageInitialized || magnetSyncMessage == null)
			{
				return;
			}
			GameNetworkManager instance = GameNetworkManager.Instance;
			if ((Object)(object)instance == (Object)null || instance.isHostingGame)
			{
				return;
			}
			try
			{
				MagnetSyncData magnetSyncData = default(MagnetSyncData);
				magnetSyncData.vehicleNetworkId = ((NetworkBehaviour)vehicle).NetworkObjectId;
				magnetSyncData.magnetedToShip = false;
				MagnetSyncData magnetSyncData2 = magnetSyncData;
				magnetSyncMessage.SendServer(magnetSyncData2);
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogWarning((object)("[Cruiser] Magnet sync hiccup (sending request): " + ex.Message));
				}
			}
		}

		private static void OnCruiserSyncReceived(CruiserSyncData data)
		{
			ApplyCruiserSyncData(data);
		}

		private static void OnCruiserSyncReceivedFromClient(CruiserSyncData data, ulong senderId)
		{
			ApplyCruiserSyncData(data);
		}

		private static void ApplyCruiserSyncData(CruiserSyncData data)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)NetworkManager.Singleton == (Object)null)
				{
					return;
				}
				VehicleController[] array = Object.FindObjectsOfType<VehicleController>();
				Vector3 val = default(Vector3);
				Quaternion val2 = default(Quaternion);
				Vector3 predictedVelocity = default(Vector3);
				VehicleController[] array2 = array;
				foreach (VehicleController val3 in array2)
				{
					if (((NetworkBehaviour)val3).NetworkObjectId != data.vehicleNetworkId)
					{
						continue;
					}
					if (!val3.localPlayerInControl)
					{
						VehicleSyncState orCreateSyncState = GetOrCreateSyncState(val3);
						orCreateSyncState.syncedMotorTorque = data.motorTorque;
						orCreateSyncState.lastMotorTorqueUpdateTime = Time.time;
						((Vector3)(ref val))..ctor(data.posX, data.posY, data.posZ);
						((Quaternion)(ref val2))..ctor(data.rotX, data.rotY, data.rotZ, data.rotW);
						((Vector3)(ref predictedVelocity))..ctor(data.velX, data.velY, data.velZ);
						float num = Time.time - orCreateSyncState.lastReceiveTime;
						if (num > 0.001f && orCreateSyncState.initialized)
						{
							Vector3 val4 = val - orCreateSyncState.targetPosition;
							orCreateSyncState.predictedVelocity = val4 / num;
						}
						else
						{
							orCreateSyncState.predictedVelocity = predictedVelocity;
						}
						orCreateSyncState.targetPosition = val;
						orCreateSyncState.targetRotation = val2;
						orCreateSyncState.lastReceivedPosition = val;
						orCreateSyncState.lastReceiveTime = Time.time;
						orCreateSyncState.usesLethalNetworkAPI = true;
						orCreateSyncState.syncedSteeringInput = data.steeringInput;
						orCreateSyncState.syncedSteeringWheelAnimFloat = data.steeringWheelAnimFloat;
						if (!orCreateSyncState.initialized)
						{
							orCreateSyncState.smoothedPosition = val;
							orCreateSyncState.smoothedRotation = val2;
							orCreateSyncState.initialized = true;
						}
					}
					break;
				}
			}
			catch
			{
			}
		}

		private static void SendCruiserSyncData(VehicleController vehicle)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected I4, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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_012f: 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_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			if (!networkMessageInitialized || cruiserSyncMessage == null || (Object)vehicle == (Object)null || !vehicle.localPlayerInControl || Time.time - lastSyncSendTime < 0.01f)
			{
				return;
			}
			lastSyncSendTime = Time.time;
			try
			{
				float motorTorque = 0f;
				if ((Object)vehicle.FrontLeftWheel != (Object)null)
				{
					motorTorque = vehicle.FrontLeftWheel.motorTorque;
				}
				CruiserSyncData cruiserSyncData = default(CruiserSyncData);
				cruiserSyncData.vehicleNetworkId = ((NetworkBehaviour)vehicle).NetworkObjectId;
				cruiserSyncData.motorTorque = motorTorque;
				cruiserSyncData.gear = (int)vehicle.gear;
				cruiserSyncData.engineRPM = vehicle.EngineRPM;
				cruiserSyncData.posX = ((Component)vehicle).transform.position.x;
				cruiserSyncData.posY = ((Component)vehicle).transform.position.y;
				cruiserSyncData.posZ = ((Component)vehicle).transform.position.z;
				cruiserSyncData.rotX = ((Component)vehicle).transform.rotation.x;
				cruiserSyncData.rotY = ((Component)vehicle).transform.rotation.y;
				cruiserSyncData.rotZ = ((Component)vehicle).transform.rotation.z;
				cruiserSyncData.rotW = ((Component)vehicle).transform.rotation.w;
				CruiserSyncData cruiserSyncData2 = cruiserSyncData;
				Rigidbody mainRigidbody = vehicle.mainRigidbody;
				cruiserSyncData2.velX = (((Object)(object)mainRigidbody != (Object)null) ? mainRigidbody.velocity.x : 0f);
				Rigidbody mainRigidbody2 = vehicle.mainRigidbody;
				cruiserSyncData2.velY = (((Object)(object)mainRigidbody2 != (Object)null) ? mainRigidbody2.velocity.y : 0f);
				Rigidbody mainRigidbody3 = vehicle.mainRigidbody;
				cruiserSyncData2.velZ = (((Object)(object)mainRigidbody3 != (Object)null) ? mainRigidbody3.velocity.z : 0f);
				cruiserSyncData2.steeringInput = vehicle.steeringInput;
				cruiserSyncData2.steeringWheelAnimFloat = ((steeringWheelAnimFloatField != null) ? ((float)steeringWheelAnimFloatField.GetValue(vehicle)) : (vehicle.steeringInput / 6f));
				CruiserSyncData cruiserSyncData3 = cruiserSyncData2;
				cruiserSyncMessage.SendOtherClients(cruiserSyncData3);
			}
			catch
			{
			}
		}

		public static void Initialize(ManualLogSource log)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Expected O, but got Unknown
			//IL_0200: Expected O, but got Unknown
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Expected O, but got Unknown
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Expected O, but got Unknown
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Expected O, but got Unknown
			//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d0: Expected O, but got Unknown
			//IL_040b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0418: Expected O, but got Unknown
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0460: Expected O, but got Unknown
			//IL_049a: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a8: Expected O, but got Unknown
			//IL_04da: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e7: Expected O, but got Unknown
			//IL_0522: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Expected O, but got Unknown
			//IL_0569: Unknown result type (might be due to invalid IL or missing references)
			//IL_0577: Expected O, but got Unknown
			//IL_05a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b6: Expected O, but got Unknown
			//IL_05e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: Expected O, but got Unknown
			//IL_0630: Unknown result type (might be due to invalid IL or missing references)
			//IL_063d: Expected O, but got Unknown
			//IL_066f: Unknown result type (might be due to invalid IL or missing references)
			//IL_067c: Expected O, but got Unknown
			//IL_06af: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bb: Expected O, but got Unknown
			//IL_06e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ec: Expected O, but got Unknown
			//IL_0708: Unknown result type (might be due to invalid IL or missing references)
			//IL_070f: Expected O, but got Unknown
			//IL_077a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0788: Expected O, but got Unknown
			//IL_0800: Unknown result type (might be due to invalid IL or missing references)
			//IL_080e: Expected O, but got Unknown
			logger = log;
			harmony = new Harmony("kr.Rohmoohyun.Cruiser_Enhancement");
			isCruiserImprovedLoaded = Chainloader.PluginInfos.ContainsKey("DiggC.CruiserImproved");
			try
			{
				Type typeFromHandle = typeof(VehicleController);
				MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "GetVehicleInput", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterCruiserInput", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo2 = AccessTools.Method(typeFromHandle, "Update", (Type[])null, (Type[])null);
				if (methodInfo2 != null)
				{
					harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterCruiserUpdate", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo3 = AccessTools.Method(typeFromHandle, "LateUpdate", (Type[])null, (Type[])null);
				if (methodInfo3 != null)
				{
					harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterCruiserLate", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				InitializeReflectionFields(typeFromHandle);
				MethodInfo methodInfo4 = AccessTools.Method(typeFromHandle, "SyncCarPositionClientRpc", (Type[])null, (Type[])null);
				if (methodInfo4 != null)
				{
					harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterCruiserPosRpc", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo5 = AccessTools.Method(typeFromHandle, "FixedUpdate", (Type[])null, (Type[])null);
				if (methodInfo5 != null)
				{
					harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(typeof(CruiserEnhancement), "BeforeCruiserFixed", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo6 = AccessTools.Method(typeFromHandle, "ActivateControl", (Type[])null, (Type[])null);
				if (methodInfo6 != null)
				{
					harmony.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterDriverSeat", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo7 = AccessTools.Method(typeFromHandle, "TryIgnition", (Type[])null, (Type[])null);
				if (methodInfo7 != null)
				{
					harmony.Patch((MethodBase)methodInfo7, new HarmonyMethod(typeof(CruiserEnhancement), "BeforeIgniteTry", (Type[])null), new HarmonyMethod(typeof(CruiserEnhancement), "AfterIgniteTry", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					if (IgnitionEasyModeEnabled)
					{
						MethodBase methodBase = AccessTools.EnumeratorMoveNext((MethodBase)methodInfo7);
						if (methodBase != null)
						{
							harmony.Patch(methodBase, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "SkipIgnitionWaits", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
						}
						else
						{
							ManualLogSource obj = logger;
							if (obj != null)
							{
								obj.LogWarning((object)"[Cruiser] TryIgnition enumerator not found — wait skip skipped");
							}
						}
					}
				}
				MethodInfo methodInfo8 = AccessTools.Method(typeFromHandle, "StartTryCarIgnition", Type.EmptyTypes, (Type[])null);
				if (methodInfo8 != null)
				{
					harmony.Patch((MethodBase)methodInfo8, new HarmonyMethod(typeof(CruiserEnhancement), "BeforeIgniteTry", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo9 = AccessTools.Method(typeof(PlayerControllerB), "DamagePlayer", new Type[7]
				{
					typeof(int),
					typeof(bool),
					typeof(bool),
					typeof(CauseOfDeath),
					typeof(int),
					typeof(bool),
					typeof(Vector3)
				}, (Type[])null);
				if (methodInfo9 != null)
				{
					harmony.Patch((MethodBase)methodInfo9, new HarmonyMethod(typeof(CruiserEnhancement), "SkipDmgInCruiser", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo10 = AccessTools.Method(typeof(PlayerControllerB), "KillPlayer", new Type[5]
				{
					typeof(Vector3),
					typeof(bool),
					typeof(CauseOfDeath),
					typeof(int),
					typeof(Vector3)
				}, (Type[])null);
				if (methodInfo10 != null)
				{
					harmony.Patch((MethodBase)methodInfo10, new HarmonyMethod(typeof(CruiserEnhancement), "SkipKillInCruiser", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo11 = AccessTools.Method(typeof(PlayerControllerB), "Update", (Type[])null, (Type[])null);
				if (methodInfo11 != null)
				{
					harmony.Patch((MethodBase)methodInfo11, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterPlyTick", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo12 = AccessTools.Method(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger", (Type[])null, (Type[])null);
				if (methodInfo12 != null)
				{
					harmony.Patch((MethodBase)methodInfo12, new HarmonyMethod(typeof(CruiserEnhancement), "BeforeTipLine", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo13 = AccessTools.Method(typeof(PlayerControllerB), "Interact_performed", (Type[])null, (Type[])null);
				if (methodInfo13 != null)
				{
					harmony.Patch((MethodBase)methodInfo13, new HarmonyMethod(typeof(CruiserEnhancement), "BeforeUseKey", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo14 = AccessTools.Method(typeFromHandle, "DoTurboBoost", (Type[])null, (Type[])null);
				if (methodInfo14 != null)
				{
					harmony.Patch((MethodBase)methodInfo14, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterTurbo", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo15 = AccessTools.Method(typeof(StartOfRound), "OnDisable", (Type[])null, (Type[])null);
				if (methodInfo15 != null)
				{
					harmony.Patch((MethodBase)methodInfo15, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "WhenRoundOff", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo16 = AccessTools.Method(typeof(GameNetworkManager), "Disconnect", (Type[])null, (Type[])null);
				if (methodInfo16 != null)
				{
					harmony.Patch((MethodBase)methodInfo16, new HarmonyMethod(typeof(CruiserEnhancement), "WhenDc", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo17 = AccessTools.Method(typeFromHandle, "Start", (Type[])null, (Type[])null);
				if (methodInfo17 != null)
				{
					harmony.Patch((MethodBase)methodInfo17, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterCruiserStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo18 = AccessTools.Method(typeFromHandle, "MagnetCarServerRpc", (Type[])null, (Type[])null);
				if (methodInfo18 != null)
				{
					harmony.Patch((MethodBase)methodInfo18, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterMagnetRpc", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo19 = AccessTools.Method(typeof(StartOfRound), "OnClientConnect", (Type[])null, (Type[])null);
				if (methodInfo19 != null)
				{
					harmony.Patch((MethodBase)methodInfo19, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "WhenClientJoins", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo20 = AccessTools.Method(typeFromHandle, "SetPassengerInCar", (Type[])null, (Type[])null);
				if (methodInfo20 != null)
				{
					harmony.Patch((MethodBase)methodInfo20, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "AfterPassengerOk", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo21 = AccessTools.Method(typeFromHandle, "SyncCarPhysicsToOtherClients", (Type[])null, (Type[])null);
				if (methodInfo21 != null)
				{
					harmony.Patch((MethodBase)methodInfo21, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(CruiserEnhancement), "FixPhysInterval", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo22 = AccessTools.Method(typeFromHandle, "SetCarEffects", (Type[])null, (Type[])null);
				if (methodInfo22 != null)
				{
					HarmonyMethod val = new HarmonyMethod(typeof(CruiserEnhancement), "BeforeCruiserFx", (Type[])null);
					val.priority = 800;
					HarmonyMethod val2 = new HarmonyMethod(typeof(CruiserEnhancement), "AfterCruiserFx", (Type[])null);
					val2.priority = 0;
					harmony.Patch((MethodBase)methodInfo22, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				MethodInfo methodInfo23 = AccessTools.Method(typeFromHandle, "DealPermanentDamage", new Type[2]
				{
					typeof(int),
					typeof(Vector3)
				}, (Type[])null);
				if (methodInfo23 != null)
				{
					harmony.Patch((MethodBase)methodInfo23, new HarmonyMethod(typeof(CruiserEnhancement), "TrimCruiserHp", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					ManualLogSource obj2 = logger;
					if (obj2 != null)
					{
						obj2.LogWarning((object)"[Cruiser] No DealPermanentDamage — skipping HP trim hook");
					}
				}
				MethodInfo methodInfo24 = AccessTools.Method(typeFromHandle, "DamagePlayerInVehicle", new Type[2]
				{
					typeof(Vector3),
					typeof(float)
				}, (Type[])null) ?? AccessTools.Method(typeFromHandle, "DamagePlayerInVehicle", (Type[])null, (Type[])null);
				if (methodInfo24 != null)
				{
					harmony.Patch((MethodBase)methodInfo24, new HarmonyMethod(typeof(CruiserEnhancement), "SoftBounceDmg", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				else
				{
					ManualLogSource obj3 = logger;
					if (obj3 != null)
					{
						obj3.LogWarning((object)"[Cruiser] No DamagePlayerInVehicle — skipping bounce hook");
					}
				}
				InitializeNetworkMessages();
				ManualLogSource obj4 = logger;
				if (obj4 != null)
				{
					obj4.LogInfo((object)"[Cruiser] Patches are in.");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj5 = logger;
				if (obj5 != null)
				{
					obj5.LogError((object)("[Cruiser] Patching blew up — " + ex.Message + "\n" + ex.StackTrace));
				}
			}
		}

		private static void UpdateControlTips(VehicleController vehicle, bool forceUpdate = false)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if ((Object)HUDManager.Instance == (Object)null || (Object)vehicle == (Object)null)
			{
				return;
			}
			bool flag = StartOfRound.Instance?.localPlayerUsingController ?? false;
			if (lastInputWasController != flag)
			{
				lastInputWasController = flag;
				forceUpdate = true;
			}
			if (tipsUpdated && !forceUpdate)
			{
				return;
			}
			try
			{
				string[] array = (lastInputWasController ? new string[4] { "가속/후진 : [RT]/[LT]", "시점 전환 : [RS]", "운전대 놓기 : [Y]", "부스트 : [A]" } : new string[4] { "가속/후진 : [W]/[S]", "시점 전환 : [V]", "운전대 놓기 : [F]", "부스트 : [Space]" });
				HUDManager.Instance.ClearControlTips();
				HUDManager.Instance.ChangeControlTipMultiple(array, false, (Item)null);
				tipsUpdated = true;
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] Control tips wonked out: " + ex.Message));
				}
			}
		}

		private static void ClearCustomTips()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			tipsUpdated = false;
			if ((Object)HUDManager.Instance != (Object)null)
			{
				HUDManager.Instance.ClearControlTips();
			}
		}

		private static void UpdatePassengerTips(VehicleController vehicle, bool forceUpdate = false)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if ((Object)HUDManager.Instance == (Object)null || (Object)vehicle == (Object)null)
			{
				return;
			}
			bool flag = StartOfRound.Instance?.localPlayerUsingController ?? false;
			if (lastInputWasController != flag)
			{
				lastInputWasController = flag;
				forceUpdate = true;
			}
			if (tipsUpdated && !forceUpdate)
			{
				return;
			}
			try
			{
				string[] array = (lastInputWasController ? new string[4] { "시점 전환 : [RS]", "내리기 : [Y]", "", "" } : new string[4] { "시점 전환 : [V]", "내리기 : [F]", "", "" });
				HUDManager.Instance.ClearControlTips();
				HUDManager.Instance.ChangeControlTipMultiple(array, false, (Item)null);
				tipsUpdated = true;
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] Passenger tips wonked out: " + ex.Message));
				}
			}
		}

		private static float SmoothThrottle(float target, float deltaTime)
		{
			target = Mathf.Clamp01(target);
			target = Mathf.Min(target, MaxThrottleInputCap);
			if (target > smoothedThrottle)
			{
				smoothedThrottle = Mathf.MoveTowards(smoothedThrottle, target, 14f * deltaTime);
			}
			else
			{
				smoothedThrottle = Mathf.MoveTowards(smoothedThrottle, target, 10f * deltaTime);
			}
			return smoothedThrottle;
		}

		private static float SmoothReverse(float target, float deltaTime)
		{
			target = Mathf.Clamp01(target);
			target = Mathf.Min(target, MaxReverseInputCap);
			if (target > smoothedReverse)
			{
				smoothedReverse = Mathf.MoveTowards(smoothedReverse, target, 6f * deltaTime);
			}
			else
			{
				smoothedReverse = Mathf.MoveTowards(smoothedReverse, target, 8f * deltaTime);
			}
			return smoothedReverse;
		}

		private static void UpdateHapticFeedback(VehicleController vehicle, float steering, Gamepad gamepad)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Invalid comparison between Unknown and I4
			//IL_0115: Invalid comparison between Unknown and I4
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			if (gamepad == null || (Object)vehicle == (Object)null || Time.time - lastHapticTime < 0.05f)
			{
				return;
			}
			lastHapticTime = Time.time;
			try
			{
				if (isBoostHapticActive)
				{
					boostHapticTimer -= Time.deltaTime;
					if (!(boostHapticTimer <= 0f))
					{
						gamepad.SetMotorSpeeds(0.7f, 0.3f);
						currentHapticLow = 0.7f;
						currentHapticHigh = 0.3f;
						return;
					}
					isBoostHapticActive = false;
					boostHapticTimer = 0f;
					gamepad.SetMotorSpeeds(0f, 0f);
					currentHapticLow = 0f;
					currentHapticHigh = 0f;
				}
				Rigidbody component = ((Component)vehicle).GetComponent<Rigidbody>();
				float num = 0f;
				float num2 = 0f;
				if ((Object)component != (Object)null)
				{
					num = Mathf.Abs(((Component)vehicle).transform.InverseTransformDirection(component.velocity).z);
					num2 = (num - lastVehicleSpeed) / Mathf.Max(Time.deltaTime, 0.001f);
					lastVehicleSpeed = num;
				}
				CarGearShift gear = vehicle.gear;
				bool flag = (int)gear == 1;
				bool flag2 = (int)gear == 2;
				bool ignitionStarted = vehicle.ignitionStarted;
				float num3 = 0f;
				float num4 = 0f;
				if (ignitionStarted)
				{
					if (flag && num > 0.5f)
					{
						float num5 = Mathf.Clamp01(num / 12f);
						num3 = Mathf.Lerp(0.03f, 0.18f, num5);
						num4 = Mathf.Lerp(0.01f, 0.08f, num5);
						if (num2 > 0.5f)
						{
							float num6 = Mathf.Clamp01(num2 / 5f) * 0.06f;
							num3 += num6;
						}
					}
					else if (flag2 && num > 0.3f)
					{
						float num7 = Mathf.Clamp01(num / 3f);
						num3 = Mathf.Lerp(0.05f, 0.15f, num7);
						num4 = Mathf.Lerp(0.02f, 0.05f, num7);
						float num8 = Mathf.Sin(Time.time * 3f % 1f * MathF.PI * 2f) * 0.5f + 0.5f;
						num3 += num8 * 0.04f * num7;
					}
					float num9 = Mathf.Abs(steering);
					if (num9 > 0.3f && num > 2f)
					{
						float num10 = (num9 - 0.3f) / 0.7f;
						float num11 = Mathf.Clamp01(num / 8f);
						float num12 = num10 * num11 * 0.06f;
						num4 = Mathf.Max(num4, num12);
					}
				}
				float num13 = 10f;
				currentHapticLow = Mathf.Lerp(currentHapticLow, num3, Time.deltaTime * num13);
				currentHapticHigh = Mathf.Lerp(currentHapticHigh, num4, Time.deltaTime * num13);
				if (currentHapticLow < 0.01f)
				{
					currentHapticLow = 0f;
				}
				if (currentHapticHigh < 0.01f)
				{
					currentHapticHigh = 0f;
				}
				gamepad.SetMotorSpeeds(currentHapticLow, currentHapticHigh);
			}
			catch
			{
			}
		}

		public static void TriggerBoostHaptic()
		{
			isBoostHapticActive = true;
			boostHapticTimer = 0.08f;
		}

		private static void StopHapticFeedback()
		{
			try
			{
				Gamepad current = Gamepad.current;
				if (current != null)
				{
					current.SetMotorSpeeds(0f, 0f);
				}
				currentHapticLow = 0f;
				currentHapticHigh = 0f;
			}
			catch
			{
			}
		}

		private static void ApplyCruiserPhysics(VehicleController vehicle)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			try
			{
				if ((Object)vehicle == (Object)null || vehicle.vehicleID != 0)
				{
					return;
				}
				int instanceID = ((Object)vehicle).GetInstanceID();
				if (!physicsModifiedCruisers.Contains(instanceID))
				{
					Rigidbody val = vehicle.mainRigidbody ?? ((Component)vehicle).GetComponent<Rigidbody>();
					if ((Object)val != (Object)null)
					{
						val.mass = 275f;
						val.drag = 0.055f;
						val.angularDrag = 1.35f;
					}
					PatchWheels(vehicle);
					physicsModifiedCruisers.Add(instanceID);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogWarning((object)("[Cruiser] Cruiser physics tweak went wrong: " + ex.Message));
				}
			}
		}

		private static void PatchWheels(VehicleController vehicle)
		{
			//IL_002f: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			if (!isCruiserImprovedLoaded && vehicle.vehicleID == 0 && !((Object)(object)vehicle.FrontLeftWheel == (Object)null) && !((Object)(object)vehicle.FrontRightWheel == (Object)null))
			{
				JointSpring val = default(JointSpring);
				val.spring = 5500f;
				val.damper = 750f;
				val.targetPosition = 0.88f;
				JointSpring suspensionSpring = val;
				vehicle.FrontLeftWheel.suspensionSpring = suspensionSpring;
				vehicle.FrontRightWheel.suspensionSpring = suspensionSpring;
				vehicle.BackLeftWheel.suspensionSpring = suspensionSpring;
				vehicle.BackRightWheel.suspensionSpring = suspensionSpring;
				vehicle.FrontLeftWheel.forceAppPointDistance = 0.56f;
				vehicle.FrontRightWheel.forceAppPointDistance = 0.56f;
				vehicle.BackLeftWheel.forceAppPointDistance = 0.56f;
				vehicle.BackRightWheel.forceAppPointDistance = 0.56f;
			}
		}

		private static void ResetPhysicsState()
		{
			smoothedThrottle = 0f;
			smoothedReverse = 0f;
			idleTimer = 0f;
			isBraking = false;
			isBoostHapticActive = false;
			boostHapticTimer = 0f;
			lastVehicleSpeed = 0f;
			visualInterpolationInitialized = false;
			StopHapticFeedback();
		}

		public static void ResetAllState()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Expected O, but got Unknown
			try
			{
				StopHapticFeedback();
				if ((Object)tpCamera != (Object)null)
				{
					((Component)tpCamera).tag = "Untagged";
					((Behaviour)tpCamera).enabled = false;
				}
				if (isThirdPerson)
				{
					Camera val = StartOfRound.Instance?.localPlayerController?.gameplayCamera;
					if ((Object)val != (Object)null)
					{
						((Component)val).tag = "MainCamera";
						((Behaviour)val).enabled = true;
					}
				}
				isThirdPerson = false;
				wasInVehicle = false;
				wasIgnitionStarted = false;
				wasLocalPlayerInControl = false;
				wasLocalPlayerInPassenger = false;
				tipsUpdated = false;
				pendingHudUpdate = false;
				hudUpdateTimer = 0f;
				pendingIgnitionSwitch = false;
				ignitionSwitchTimer = 0f;
				cameraRetryCount = 0;
				cameraVerifyTimer = 0f;
				smoothedThrottle = 0f;
				smoothedReverse = 0f;
				idleTimer = 0f;
				isBraking = false;
				isBoostHapticActive = false;
				boostHapticTimer = 0f;
				currentHapticLow = 0f;
				currentHapticHigh = 0f;
				vehicleSyncStates.Clear();
				lastSyncSendTime = 0f;
				physicsModifiedCruisers.Clear();
				currentVehicle = null;
				lastKnownVehicle = null;
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] Reset state blew up: " + ex.Message));
				}
			}
		}

		private static void WhenRoundOff()
		{
			ResetAllState();
		}

		private static void WhenDc()
		{
			ResetAllState();
		}

		public static void ToggleCamera(VehicleController vehicle)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			isThirdPerson = !isThirdPerson;
			currentVehicle = vehicle;
			if (isThirdPerson)
			{
				InitializeTPCamera(vehicle);
				if ((Object)tpCamera != (Object)null)
				{
					Camera val = (originalMainCamera = StartOfRound.Instance.localPlayerController.gameplayCamera);
					if ((Object)val != (Object)null)
					{
						((Component)val).tag = "Untagged";
						((Behaviour)val).enabled = false;
					}
					((Component)tpCamera).tag = "MainCamera";
					((Behaviour)tpCamera).enabled = true;
					tpCamera.depth = 100f;
				}
			}
			else
			{
				Camera gameplayCamera = StartOfRound.Instance.localPlayerController.gameplayCamera;
				if ((Object)tpCamera != (Object)null)
				{
					((Component)tpCamera).tag = "Untagged";
					((Behaviour)tpCamera).enabled = false;
				}
				if ((Object)gameplayCamera != (Object)null)
				{
					((Component)gameplayCamera).tag = "MainCamera";
					((Behaviour)gameplayCamera).enabled = true;
				}
			}
		}

		public static void EnableThirdPersonOnIgnition(VehicleController vehicle)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			if (!isThirdPerson && (Object)vehicle != (Object)null && vehicle.localPlayerInControl)
			{
				ToggleCamera(vehicle);
			}
		}

		public static void ResetToFirstPerson()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			if (isThirdPerson && (Object)tpCamera != (Object)null)
			{
				isThirdPerson = false;
				((Component)tpCamera).tag = "Untagged";
				((Behaviour)tpCamera).enabled = false;
				Camera val = StartOfRound.Instance?.localPlayerController?.gameplayCamera;
				if ((Object)val != (Object)null)
				{
					((Component)val).tag = "MainCamera";
					((Behaviour)val).enabled = true;
				}
			}
			wasIgnitionStarted = false;
			wasLocalPlayerInControl = false;
			wasLocalPlayerInPassenger = false;
			lastKnownVehicle = null;
			ResetPhysicsState();
			ClearCustomTips();
		}

		public static void SwitchToSpectate()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (isThirdPerson && (Object)tpCamera != (Object)null)
			{
				isThirdPerson = false;
				((Component)tpCamera).tag = "Untagged";
				((Behaviour)tpCamera).enabled = false;
				Camera val = StartOfRound.Instance?.localPlayerController?.gameplayCamera;
				if ((Object)val != (Object)null)
				{
					((Component)val).tag = "MainCamera";
					((Behaviour)val).enabled = true;
				}
				StartOfRound.Instance.SwitchCamera(StartOfRound.Instance.spectateCamera);
			}
			wasIgnitionStarted = false;
			wasLocalPlayerInControl = false;
			wasLocalPlayerInPassenger = false;
			ResetPhysicsState();
			ClearCustomTips();
		}

		private static void InitializeTPCamera(VehicleController vehicle)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: 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_00b1: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			currentVehicle = vehicle;
			if ((Object)tpCamera == (Object)null)
			{
				tpCamera = new GameObject("Cruiser_Enhancement_TPCamera").AddComponent<Camera>();
				Camera gameplayCamera = StartOfRound.Instance.localPlayerController.gameplayCamera;
				tpCamera.CopyFrom(gameplayCamera);
				tpCamera.nearClipPlane = 0.1f;
				tpCamera.farClipPlane = 1000f;
			}
			visualVehiclePosition = ((Component)vehicle).transform.position;
			visualVehicleRotation = ((Component)vehicle).transform.rotation;
			visualVelocity = Vector3.zero;
			visualInterpolationInitialized = true;
			currentCameraPos = CalculateCameraPosition(vehicle, ((Component)vehicle).transform.position, ((Component)vehicle).transform.forward);
			((Component)tpCamera).transform.position = currentCameraPos;
			((Component)tpCamera).transform.LookAt(((Component)vehicle).transform.position + Vector3.up * 1.5f);
		}

		private static Vector3 CalculateCameraPosition(VehicleController vehicle, Vector3 vehiclePos, Vector3 vehicleForward)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			return vehiclePos - vehicleForward * cameraBackDistance + Vector3.up * cameraUpDistance;
		}

		private static void UpdateVisualInterpolation(VehicleController vehicle)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			Vector3 position = ((Component)vehicle).transform.position;
			Quaternion rotation = ((Component)vehicle).transform.rotation;
			float num = Vector3.Distance(visualVehiclePosition, position);
			if (!visualInterpolationInitialized || num > 15f)
			{
				visualVehiclePosition = position;
				visualVehicleRotation = rotation;
				visualVelocity = Vector3.zero;
				visualInterpolationInitialized = true;
			}
			else
			{
				visualVehiclePosition = Vector3.SmoothDamp(visualVehiclePosition, position, ref visualVelocity, 0.08f);
				visualVehicleRotation = Quaternion.Slerp(visualVehicleRotation, rotation, Time.deltaTime * 20f);
			}
		}

		public static void UpdateGTACamera(VehicleController vehicle)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			if (isThirdPerson && !((Object)tpCamera == (Object)null) && !((Object)vehicle == (Object)null))
			{
				currentVehicle = vehicle;
				bool num = (Object)GameNetworkManager.Instance != (Object)null && !GameNetworkManager.Instance.isHostingGame;
				bool flag = vehicle.localPlayerInPassengerSeat && !vehicle.localPlayerInControl;
				Vector3 position;
				Vector3 val;
				if (num && flag)
				{
					UpdateVisualInterpolation(vehicle);
					position = visualVehiclePosition;
					val = visualVehicleRotation * Vector3.forward;
				}
				else
				{
					position = ((Component)vehicle).transform.position;
					val = ((Component)vehicle).transform.forward;
					visualVehiclePosition = position;
					visualVehicleRotation = ((Component)vehicle).transform.rotation;
					visualInterpolationInitialized = true;
				}
				Vector3 val2 = CalculateCameraPosition(vehicle, position, val);
				currentCameraPos = Vector3.SmoothDamp(currentCameraPos, val2, ref cameraVelocity, 1f / cameraSmoothSpeed);
				((Component)tpCamera).transform.position = currentCameraPos;
				Quaternion val3 = Quaternion.LookRotation(position + val * cameraLookAhead + Vector3.up * 1.2f - ((Component)tpCamera).transform.position);
				((Component)tpCamera).transform.rotation = Quaternion.Slerp(((Component)tpCamera).transform.rotation, val3, Time.deltaTime * 5f);
			}
		}

		private static void TryExitDriverLocal(VehicleController vehicle)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			if ((Object)vehicle == (Object)null || driverExitLocalMethod == null)
			{
				return;
			}
			try
			{
				driverExitLocalMethod.Invoke(vehicle, null);
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] 3rd person exit (reflection) failed: " + ex.Message));
				}
			}
		}

		public static void ExitVehicleFromThirdPerson(VehicleController vehicle)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			if (!((Object)vehicle == (Object)null))
			{
				PlayerControllerB val = StartOfRound.Instance?.localPlayerController;
				if (!((Object)val == (Object)null))
				{
					val.CancelSpecialTriggerAnimations();
					ResetToFirstPerson();
					TryExitDriverLocal(vehicle);
				}
			}
		}

		private static void TrimCruiserHp(VehicleController __instance, ref int damageAmount, Vector3 damagePosition)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			try
			{
				if (isCruiserImprovedLoaded || damageAmount <= 0 || __instance.carDestroyed || !((NetworkBehaviour)__instance).IsOwner || __instance.magnetedToShip)
				{
					return;
				}
				StartOfRound instance = StartOfRound.Instance;
				if (!((Object)instance == (Object)null) && ((Object)(object)instance.testRoom != (Object)null || !instance.inShipPhase))
				{
					float cruiserDamageMultiplier = CruiserDamageMultiplier;
					if (!(cruiserDamageMultiplier >= 0.999f))
					{
						damageAmount = Mathf.Max(0, Mathf.RoundToInt((float)damageAmount * cruiserDamageMultiplier));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] Cruiser HP hook: " + ex.Message));
				}
			}
		}

		private static bool SoftBounceDmg(VehicleController __instance, Vector3 vel, float magnitude)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if (!SoftCruiserCollisionDamage)
			{
				return true;
			}
			try
			{
				if ((Object)HUDManager.Instance == (Object)null)
				{
					return true;
				}
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)val == (Object)null)
				{
					return true;
				}
				if (__instance.localPlayerInPassengerSeat || __instance.localPlayerInControl)
				{
					if (magnitude > 24f)
					{
						HUDManager.Instance.ShakeCamera((ScreenShakeType)3);
					}
					else
					{
						HUDManager.Instance.ShakeCamera((ScreenShakeType)1);
					}
				}
				else if ((Object)(object)__instance.physicsRegion.physicsTransform == (Object)(object)val.physicsParent && (Object)(object)val.overridePhysicsParent == (Object)null)
				{
					HUDManager.Instance.ShakeCamera((ScreenShakeType)0);
					val.externalForceAutoFade += vel;
				}
				return false;
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] In-cruiser damage hook: " + ex.Message));
				}
				return true;
			}
		}

		private static void AfterDriverSeat(VehicleController __instance)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			try
			{
				if (!__instance.localPlayerInControl)
				{
					return;
				}
				PlayerControllerB val = StartOfRound.Instance?.localPlayerController;
				if (!((Object)val == (Object)null))
				{
					if (__instance.honkingHorn)
					{
						__instance.SetHonkingLocalClient(false);
					}
					if ((Object)val.hoveringOverTrigger != (Object)null)
					{
						val.hoveringOverTrigger = null;
					}
					pendingHornCheck = true;
					hornCheckTimer = 0f;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] Driver seat hook failed: " + ex.Message));
				}
			}
		}

		private static void AfterIgniteTry(VehicleController __instance)
		{
			try
			{
				if (__instance.localPlayerInControl)
				{
					if (__instance.ignitionStarted && !wasIgnitionStarted && !isThirdPerson)
					{
						wasIgnitionStarted = true;
						pendingIgnitionSwitch = true;
						ignitionSwitchTimer = 0f;
					}
					else if (__instance.ignitionStarted && !isThirdPerson && !pendingIgnitionSwitch)
					{
						pendingIgnitionSwitch = true;
						ignitionSwitchTimer = 0f;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] Ignition hook tripped: " + ex.Message));
				}
			}
		}

		private static void ApplyIgnitionChanceBoost(VehicleController vehicle)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			if (!IgnitionEasyModeEnabled || chanceToStartIgnitionField == null || (Object)vehicle == (Object)null)
			{
				return;
			}
			try
			{
				chanceToStartIgnitionField.SetValue(vehicle, 100f);
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogWarning((object)("[Cruiser] Couldn't bump ignition chance: " + ex.Message));
				}
			}
		}

		private static void BeforeIgniteTry(VehicleController __instance)
		{
			if (__instance.localPlayerInControl && !__instance.ignitionStarted)
			{
				ApplyIgnitionChanceBoost(__instance);
			}
		}

		private static IEnumerable<CodeInstruction> SkipIgnitionWaits(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 2; i < list.Count; i++)
			{
				if (list[i].opcode == OpCodes.Stfld && list[i - 1].opcode == OpCodes.Newobj && list[i - 2].opcode == OpCodes.Ldc_R4)
				{
					list[i - 2].operand = 0f;
				}
			}
			return list;
		}

		private static bool LocalPlayerIsInThisCruiser(VehicleController cruiser, PlayerControllerB player)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			if ((Object)cruiser == (Object)null || (Object)player == (Object)null)
			{
				return false;
			}
			if (!cruiser.localPlayerInControl)
			{
				return cruiser.localPlayerInPassengerSeat;
			}
			return true;
		}

		private static bool SkipDmgInCruiser(PlayerControllerB __instance, int damageNumber, bool hasDamageSFX, bool callRPC, CauseOfDeath causeOfDeath, int deathAnimation, bool fallDamage, Vector3 force)
		{
			//IL_0034: 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_0044: Expected O, but got Unknown
			//IL_0044: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_00c1: Expected O, but got Unknown
			if (!PlayerInvincibleInCruiser)
			{
				return true;
			}
			try
			{
				if (!__instance.isPlayerControlled || __instance.isPlayerDead)
				{
					return true;
				}
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)__instance != (Object)val)
				{
					return true;
				}
				VehicleController val2 = StartOfRound.Instance?.attachedVehicle ?? (((Object)lastKnownVehicle != (Object)null && !lastKnownVehicle.carDestroyed) ? lastKnownVehicle : null);
				if ((Object)val2 == (Object)null || val2.carDestroyed)
				{
					return true;
				}
				if (!LocalPlayerIsInThisCruiser(val2, val) && (Object)val2 != (Object)lastKnownVehicle)
				{
					return true;
				}
				return false;
			}
			catch
			{
				return true;
			}
		}

		private static bool SkipKillInCruiser(PlayerControllerB __instance, Vector3 bodyVelocity, bool spawnBody, CauseOfDeath causeOfDeath, int deathAnimation, Vector3 positionOffset)
		{
			//IL_0034: 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_0044: Expected O, but got Unknown
			//IL_0044: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00ca: Expected O, but got Unknown
			if (!PlayerInvincibleInCruiser)
			{
				return true;
			}
			try
			{
				if (!__instance.isPlayerControlled || __instance.isPlayerDead)
				{
					return true;
				}
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)__instance != (Object)val)
				{
					return true;
				}
				VehicleController val2 = StartOfRound.Instance?.attachedVehicle ?? (((Object)lastKnownVehicle != (Object)null && !lastKnownVehicle.carDestroyed) ? lastKnownVehicle : null);
				if ((Object)val2 == (Object)null)
				{
					return true;
				}
				if (val2.carDestroyed)
				{
					ResetToFirstPerson();
					return true;
				}
				if (!LocalPlayerIsInThisCruiser(val2, val) && (Object)val2 != (Object)lastKnownVehicle)
				{
					return true;
				}
				return false;
			}
			catch
			{
				return true;
			}
		}

		private static void AfterTurbo(VehicleController __instance)
		{
			try
			{
				if (__instance.localPlayerInControl)
				{
					TriggerBoostHaptic();
				}
			}
			catch
			{
			}
		}

		private static void AfterCruiserInput(VehicleController __instance)
		{
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected I4, but got Unknown
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Invalid comparison between Unknown and I4
			//IL_02c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Expected O, but got Unknown
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: 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_0318: Invalid comparison between Unknown and I4
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_041d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ab: 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_03bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: 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)
			try
			{
				if (!__instance.localPlayerInControl)
				{
					return;
				}
				float deltaTime = Time.deltaTime;
				Gamepad current = Gamepad.current;
				Keyboard current2 = Keyboard.current;
				float x = __instance.moveInputVector.x;
				float num = 0f;
				float num2 = 0f;
				float num3 = 0f;
				if (current != null)
				{
					float num4 = ((InputControl<float>)(object)current.rightTrigger).ReadValue();
					float num5 = ((InputControl<float>)(object)current.leftTrigger).ReadValue();
					num3 = ((InputControl<float>)(object)((Vector2Control)current.leftStick).x).ReadValue();
					num = ((num4 > 0.1f) ? num4 : 0f);
					num2 = ((num5 > 0.1f) ? num5 : 0f);
				}
				if (current2 != null)
				{
					if (((ButtonControl)current2.wKey).isPressed)
					{
						num = Mathf.Max(num, 1f);
					}
					if (((ButtonControl)current2.sKey).isPressed)
					{
						num2 = Mathf.Max(num2, 1f);
					}
				}
				float num6 = ((Mathf.Abs(num3) > 0.1f) ? num3 : x);
				if (Mathf.Abs(num6) > 0.05f)
				{
					__instance.steeringInput = num6 * STEERING_MULTIPLIER;
				}
				else
				{
					__instance.steeringInput = 0f;
				}
				float num7 = SmoothThrottle(num, deltaTime);
				float num8 = SmoothReverse(num2, deltaTime);
				float num9 = num7 - num8;
				float num10 = Vector3.Dot(((Component)__instance).transform.forward, Vector3.up);
				if (!__instance.ignitionStarted)
				{
					__instance.moveInputVector = new Vector2(num6, num9);
					return;
				}
				int num11 = (int)__instance.gear;
				if (num > 0.05f)
				{
					idleTimer = 0f;
					isBraking = false;
					if (num11 != 1)
					{
						__instance.ShiftToGearAndSync(1);
					}
					__instance.drivePedalPressed = true;
					__instance.brakePedalPressed = false;
				}
				else if (num2 > 0.05f)
				{
					idleTimer = 0f;
					isBraking = false;
					if (num11 != 2)
					{
						__instance.ShiftToGearAndSync(2);
					}
					__instance.drivePedalPressed = true;
					__instance.brakePedalPressed = false;
				}
				else
				{
					idleTimer += deltaTime;
					float num12 = Mathf.Lerp(0.4f, 0.72f, Mathf.Clamp01((num10 - 0.05f) / 0.18f));
					if (idleTimer >= num12)
					{
						if (!isBraking)
						{
							isBraking = true;
						}
						__instance.drivePedalPressed = false;
						__instance.brakePedalPressed = true;
					}
					else
					{
						__instance.drivePedalPressed = false;
						__instance.brakePedalPressed = false;
					}
				}
				float num13 = Mathf.Clamp(UphillAssistMultiplier, 0f, 1.5f);
				if ((int)__instance.gear == 1 && num9 > 0.02f && num10 > 0.03f && num13 > 0.001f)
				{
					float num14 = Mathf.Clamp01((num10 - 0.03f) / 0.42f);
					float num15 = 0.38f * num13;
					float num16 = 1f + 0.27999997f * num13;
					float num17 = 1f + num14 * num15;
					num9 = Mathf.Min(num16, num9 * num17);
				}
				__instance.moveInputVector = new Vector2(num6, num9);
				Rigidbody component = ((Component)__instance).GetComponent<Rigidbody>();
				if ((Object)component != (Object)null)
				{
					Vector3 velocity = component.velocity;
					Vector3 val = ((Component)__instance).transform.InverseTransformDirection(velocity);
					float z = val.z;
					float mAX_FORWARD_SPEED = MAX_FORWARD_SPEED;
					if ((int)__instance.gear == 1 && num > 0.05f && num10 > 0.07f && __instance.ignitionStarted && num13 > 0.001f)
					{
						float num18 = Mathf.Clamp01((MAX_FORWARD_SPEED * 0.92f - z) / (MAX_FORWARD_SPEED * 0.38f));
						if (num18 > 0.02f)
						{
							float num19 = Mathf.Clamp01((num10 - 0.07f) / 0.38f);
							float num20 = 26f * num13 * num19 * Mathf.Clamp01(num) * num18;
							component.AddForce(((Component)__instance).transform.forward * num20, (ForceMode)5);
							velocity = component.velocity;
							val = ((Component)__instance).transform.InverseTransformDirection(velocity);
							z = val.z;
						}
					}
					bool flag = false;
					if (z > mAX_FORWARD_SPEED)
					{
						val.z = mAX_FORWARD_SPEED;
						flag = true;
					}
					else if (z < 0f - MAX_REVERSE_SPEED)
					{
						val.z = 0f - MAX_REVERSE_SPEED;
						flag = true;
					}
					if (flag)
					{
						component.velocity = ((Component)__instance).transform.TransformDirection(val);
					}
				}
				if (current != null)
				{
					UpdateHapticFeedback(__instance, num6, current);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource obj = logger;
				if (obj != null)
				{
					obj.LogError((object)("[Cruiser] Input hook died: " + ex.Message));
				}
			}
		}

		private static void AfterCruiserUpdate(VehicleController __instance)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Expected O, but got Unknown
			//IL_0604: Unknown result type (might be due to invalid IL or missing references)
			//IL_060f: Expected O, but got Unknown
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c5: Expected O, but got Unknown
			//IL_0670: Unknown result type (might be due to invalid IL or missing references)
			//IL_067b: Expected O, but got Unknown
			try
			{
				if ((Object)(StartOfRound.Instance?.localPlayerController) == (Object)null)
				{
					return;
				}
				if (__instance.localPlayerInControl || __instance.localPlayerInPassengerSeat)
				{
					lastKnownVehicle = __instance;
				}
				if (__instance.localPlayerInControl && !((NetworkBehaviour)__instance).IsOwner && __instance.ignitionStarted && syncCruiserPhysicsMethod != null)
				{
					try
					{
						syncCruiserPhysicsMethod.Invoke(__instance, null);
					}
					catch
					{
					}
				}
				if (__instance.localPlayerInControl && __instance.ignitionStarted)
				{
					SendCruiserSyncData(__instance);
				}
				if (!__instance.localPlayerInControl)
				{
					if (wasLocalPlayerInControl)
					{
						wasLocalPlayerInControl = false;
						if (isThirdPerson)
						{
							ResetToFirstPerson();
						}
						ResetPhysicsState();
						ClearCustomTips();
					}
					if (__instance.localPlayerInPassengerSeat)
					{
						if (!wasLocalPlayerInPassenger)
						{
							wasLocalPlayerInPassenger = true;
							wasIgnitionStarted = false;
							tipsUpdated = false;
							pendingIgnitionSwitch = false;
							ignitionSwitchTimer = 0f;
							if (__instance.ignitionStarted && !isThirdPerson)
							{
								wasIgnitionStarted = true;
								pendingIgnitionSwitch = true;
								ignitionSwitchTimer = 0f;
							}
						}
						if (__instance.ignitionStarted && !wasIgnitionStarted)
						{
							wasIgnitionStarted = true;
							if (!isThirdPerson)
							{
								pendingIgnitionSwitch = true;
								ignitionSwitchTimer = 0f;
							}
						}
						else if (!__instance.ignitionStarted && wasIgnitionStarted)
						{
							wasIgnitionStarted = false;
							pendingIgnitionSwitch = false;
							ignitionSwitchTimer = 0f;
						}
						UpdatePassengerTips(__instance);
						if (pendingIgnitionSwitch && __instance.ignitionStarted)
						{
							ignitionSwitchTimer += Time.deltaTime;
							if (ignitionSwitchTimer >= 0.3f)
							{
								pendingIgnitionSwitch = false;
								ignitionSwitchTimer = 0f;
								if (!isThirdPerson)
								{
									ToggleCamera(__instance);
									cameraRetryCount = 0;
									cameraVerifyTimer = 0.1f;
									tipsUpdated = false;
									UpdatePassengerTips(__instance);
								}
							}
						}
						if (pendingPassengerExit && (Object)pendingExitVehicle != (Object)null)
						{
							passengerExitTimer += Time.deltaTime;
							if (passengerExitTimer >= 0.4f)
							{
								pendingExitVehicle.ExitPassengerSideSeat();
								pendingExitVehicle.OnPassengerExit();
								ResetToFirstPerson();
								pendingPassengerExit = false;
								passengerExitTimer = 0f;
								pendingExitVehicle = null;
							}
						}
						if (cameraVerifyTimer > 0f && isThirdPerson && (Object)tpCamera != (Object)null)
						{
							cameraVerifyTimer -= Time.deltaTime;
							if (cameraVerifyTimer <= 0f)
							{
								if (((Component)tpCamera).tag != "MainCamera" && cameraRetryCount < 5)
								{
									cameraRetryCount++;
									Camera gameplayCamera = StartOfRound.Instance.localPlayerController.gameplayCamera;
									if ((Object)gameplayCamera != (Object)null)
									{
										((Component)gameplayCamera).tag = "Untagged";
										((Behaviour)gameplayCamera).enabled = false;
									}
									((Component)tpCamera).tag = "MainCamera";
									((Behaviour)tpCamera).enabled = true;
									cameraVerifyTimer = 0.1f;
								}
								else
								{
									cameraVerifyTimer = 0f;
								}
							}
						}
						Gamepad current = Gamepad.current;
						Keyboard current2 = Keyboard.current;
						bool flag = false;
						if (current2 != null && ((ButtonControl)current2.vKey).wasPressedThisFrame)
						{
							flag = true;
						}
						if (current != null && current.rightStickButton.wasPressedThisFrame)
						{
							flag = true;
						}
						if (flag)
						{
							ToggleCamera(__instance);
							tipsUpdated = false;
							UpdatePassengerTips(__instance, forceUpdate: true);
						}
						bool flag2 = false;
						if (current2 != null && ((ButtonControl)current2.fKey).wasPressedThisFrame)
						{
							flag2 = true;
						}
						if (current != null && current.buttonNorth.wasPressedThisFrame)
						{
							flag2 = true;
						}
						if (flag2 && !pendingPassengerExit)
						{
							if (!__instance.passengerSideDoor.boolValue)
							{
								__instance.passengerSideDoor.TriggerAnimation(StartOfRound.Instance.localPlayerController);
							}
							pendingPassengerExit = true;
							passengerExitTimer = 0f;
							pendingExitVehicle = __instance;
						}
					}
					else if (wasLocalPlayerInPassenger)
					{
						wasLocalPlayerInPassenger = false;
						if (isThirdPerson)
						{
							ResetToFirstPerson();
						}
						ClearCustomTips();
					}
					return;
				}
				if (!wasLocalPlayerInControl)
				{
					wasLocalPlayerInControl = true;
					wasIgnitionStarted = false;
					tipsUpdated = false;
					pendingIgnitionSwitch = false;
					ignitionSwitchTimer = 0f;
					lastInputWasController = StartOfRound.Instance?.localPlayerUsingController ?? false;
					pendingHudUpdate = true;
					hudUpdateTimer = 0f;
					if (__instance.ignitionStarted && !isThirdPerson)
					{
						wasIgnitionStarted = true;
						pendingIgnitionSwitch = true;
						ignitionSwitchTimer = 0f;
					}
				}
				if (pendingHornCheck && __instance.localPlayerInControl)
				{
					hornCheckTimer += Time.deltaTime;
					if (__instance.honkingHorn)
					{
						__instance.SetHonkingLocalClient(false);
					}
					if (hornCheckTimer >= 0.5f)
					{
						pendingHornCheck = false;
						hornCheckTimer = 0f;
					}
				}
				if (__instance.ignitionStarted && !wasIgnitionStarted)
				{
					wasIgnitionStarted = true;
					if (!isThirdPerson && !pendingIgnitionSwitch)
					{
						pendingIgnitionSwitch = true;
						ignitionSwitchTimer = 0f;
					}
					tipsUpdated = false;
				}
				else if (!__instance.ignitionStarted && wasIgnitionStarted)
				{
					wasIgnitionStarted = false;
					pendingIgnitionSwitch = false;
					ignitionSwitchTimer = 0f;
				}
				if (pendingHudUpdate)
				{
					hudUpdateTimer += Time.deltaTime;
					if (hudUpdateTimer >= 0.15f)
					{
						pendingHudUpdate = false;
						hudUpdateTimer = 0f;
						UpdateControlTips(__instance, forceUpdate: true);
					}
				}
				if (__instance.ignitionStarted && !pendingHudUpdate)
				{
					UpdateControlTips(__instance);
				}
				if (pendingIgnitionSwitch && __instance.ignitionStarted)
				{
					ignitionSwitchTimer += Time.deltaTime;
					if (ignitionSwitchTimer >= 0.3f)
					{
						pendingIgnitionSwitch = false;
						ignitionSwitchTimer = 0f;
						if (!isThirdPerson)
						{
							ToggleCamera(__instance);
							cameraRetryCount = 0;
							cameraVerifyTimer = 0.1f;
							tipsUpdated = false;
							UpdateControlTips(__instance, forceUpdate: true);
						}
					}
				}
				else if (pendingIgnitionSwitch && !__instance.ignitionStarted)
				{
					pendingIgnitionSwitch = false;
					ignitionSwitchTimer = 0f;
				}
				if (cameraVerifyTimer > 0f && isThirdPerson && (Object)tpCamera != (Object)null)
				{
					cameraVerifyTimer -= Time.deltaTime;
					if (cameraVerifyTimer <= 0f)
					{
						if (((Component)tpCamera).tag != "MainCamera" && cameraRetryCount < 5)
						{
							cameraRetryCount++;
							Camera gameplayCamera2 = StartOfRound.Instance.localPlayerController.gameplayCamera;
							if ((Object)gameplayCamera2 != (Object)null)
							{
								((Component)gameplayCamera2).tag = "Untagged";
								((Behaviour)gameplayCamera2).enabled = false;
							}
							((Component)tpCamera).tag = "MainCamera";
							((Behaviour)tpCamera).enabled = true;
							cameraVerifyTimer = 0.1f;
						}
						else
						{
							cameraVerifyTimer = 0f;
						}
					}
				}
				Gamepad current3 = Gamepad.current;
				Keyboard current4 = Keyboard.current;
				bool flag3 = false;
				if (current4 != null && ((ButtonControl)current4.vKey).wasPressedThisFrame)
				{
					flag3 = true;
				}
				if (current3 != null && current3.rightStickButton.wasPressedThisFrame)
				{
					flag3 = true;
				}
				if (flag3)
				{
					ToggleCamera(__instance);
				}
				bool flag4 = false;
				if (current4 != null && ((ButtonControl)current4.fKey).wasPressedThisFrame)
				{
					flag4 = true;
				}
				if (current3 != null && current3.buttonNorth.wasPressedThisFrame)
				{
					flag4 = true;
				}
				if (flag4)
				{
					ExitVehicleFromThirdPerson(__instance);
				}
				ApplyTireEffectsForObserver(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource obj2 = logger;
				if (obj2 != null)
				{
					obj2.LogError((object)("[Cruiser] Cruiser Update hook died: " + ex.Message));
				}
			}
		}

		private static void AfterCruiserLate(VehicleController __instance)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			try
			{
				if (__instance.localPlayerInControl || __instance.localPlayerInPassengerSeat)
				{
					UpdateGTACamera(__instance);
				}
				if (__instance.localPlayerInControl || !((Object)__instance.currentDriver != (Object)null))
				{
					return;
				}
				VehicleSyncState orCreateSyncState = GetOrCreateSyncState(__instance);
				if (orCreateSyncState != null && orCreateSyncState.initialized && orCreateSyncState.usesLethalNetworkAPI)
				{
					if (steeringWheelAnimFloatField != null)
					{
						steeringWheelAnimFloatField.SetValue(__instance, orCreateSyncState.syncedSteeringWheelAnimFloat);
					}
					__instance.steeringInput = orCreateSyncState.syncedSteeringInput;
				}
				ApplyTireEffectsForObserver(__instance);
			}
			catch
			{
			}
		}

		private static void ApplyTireEffectsForObserver(VehicleController vehicle)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Expected O, but got Unknown
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			if (vehicle.localPlayerInControl || vehicle.carDestroyed || vehicle.magnetedToShip || !vehicle.ignitionStarted || (Object)vehicle.currentDriver == (Object)null || (Object)vehicle.tireSparks == (Object)null)
			{
				return;
			}
			VehicleSyncState orCreateSyncState = GetOrCreateSyncState(vehicle);
			if (!orCreateSyncState.initialized)
			{
				return;
			}
			float syncedMotorTorque = orCreateSyncState.syncedMotorTorque;
			float magnitude = ((Vector3)(ref orCreateSyncState.predictedVelocity)).magnitude;
			bool num = syncedMotorTorque > 900f && magnitude > 8f;
			bool flag = (syncedMotorTorque > 600f && magnitude > 5f) || (Mathf.Abs(vehicle.steeringInput) > 1.5f && magnitude > 6f);
			if (num)
			{
				if (!vehicle.tireSparks.isPlaying)
				{
					vehicle.tireSparks.Play(true);
				}
			}
			else if (vehicle.tireSparks.isPlaying)
			{
				vehicle.tireSparks.Stop(true, (ParticleSystemStopBehavior)1);
			}
			if (!((Object)vehicle.skiddingAudio != (Object)null))
			{
				return;
			}
			if (flag)
			{
				float num2 = Mathf.Clamp01((syncedMotorTorque - 600f) / 400f) * 0.5f;
				if (!vehicle.skiddingAudio.isPlaying)
				{
					vehicle.skiddingAudio.Play();
				}
				vehicle.skiddingAudio.volume = Mathf.Lerp(vehicle.skiddingAudio.volume, num2, Time.deltaTime * 5f);
			}
			else
			{
				vehicle.skiddingAudio.volume = Mathf.Lerp(vehicle.skiddingAudio.volume, 0f, Time.deltaTime * 5f);
				if (vehicle.skiddingAudio.volume < 0.01f && vehicle.skiddingAudio.isPlaying)
				{
					vehicle.skiddingAudio.Stop();
				}
			}
		}

		private static void BeforeCruiserFx(VehicleController __instance, ref float setSteering)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			try
			{
				if (!isCruiserImprovedLoaded && __instance.localPlayerInControl && __instance.vehicleID == 0)
				{
					setSteering = 0f;
					steeringWheelAnimFloatField?.SetValue(__instance, Mathf.Clamp(__instance.steeringInput / 6f, -0.99f, 0.99f));
				}
				if (!__instance.localPlayerInControl && !((Object)__instance.currentDriver == (Object)null) && __instance.ignitionStarted && !__instance.carDestroyed && !__instance.magnetedToShip && !((Object)__instance.FrontLeftWheel == (Object)null) && !((Object)__instance.FrontRightWheel == (Object)null))
				{
					savedMotorTorqueLeft = __instance.FrontLeftWheel.motorTorque;
					savedMotorTorqueRight = __instance.FrontRightWheel.motorTorque;
					VehicleSyncState orCreateSyncState = GetOrCreateSyncState(__instance);
					if (orCreateSyncState == null || !orCreateSyncState.initialized)
					{
						motorTorqueOverridden = false;
						return;
					}
					float syncedMotorTorque = orCreateSyncState.syncedMotorTorque;
					__instance.FrontLeftWheel.motorTorque = syncedMotorTorque;
					__instance.FrontRightWheel.motorTorque = syncedMotorTorque;
					motorTorqueOverridden = true;
				}
			}
			catch
			{
				motorTorqueOverridden = false;
			}
		}

		private static void AfterCruiserFx(VehicleController __instance, float setSteering)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			try
			{
				if (!__instance.localPlayerInControl && motorTorqueOverridden)
				{
					if ((Object)__instance.FrontLeftWheel != (Object)null)
					{
						__instance.FrontLeftWheel.motorTorque = savedMotorTorqueLeft;
					}
					if ((Object)__instance.FrontRightWheel != (Object)null)
					{
						__instance.FrontRightWheel.motorTorque = savedMotorTorqueRight;
					}
					motorTorqueOverridden = false;
				}
			}
			catch
			{
				motorTorqueOverr