Decompiled source of HoverHauler v1.0.0

HoverHauler.dll

Decompiled 7 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HoverHauler
{
	internal static class Hover
	{
		private sealed class State
		{
			internal bool HasFloor;

			internal float FloorY;

			internal float Height = -1f;

			internal float RestOffset = -1f;

			internal Vector3 LastPos;

			internal bool Hovering;

			internal int Input;

			internal float InputTime;

			internal bool Locked;

			internal RigidbodyConstraints SavedConstraints;

			internal bool WasDriving;

			internal bool LoggedHole;
		}

		[HarmonyPatch(typeof(ItemVehicle), "PerformGroundCheck")]
		internal static class GroundCheckPatch
		{
			private static void Postfix(ItemVehicle __instance)
			{
				//IL_0052: 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_0083: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (!IsHoverVehicle(__instance))
					{
						return;
					}
					State state = Get(__instance);
					bool num = FrontGrounded.Invoke(__instance);
					bool flag = BackGrounded.Invoke(__instance);
					if (num && flag && !state.Hovering && Object.op_Implicit((Object)(object)__instance.rb) && Mathf.Abs(__instance.rb.velocity.y) < 0.5f && Probe(__instance, __instance.rb.worldCenterOfMass, out var groundY))
					{
						float num2 = __instance.rb.worldCenterOfMass.y - groundY;
						if (num2 > 0.05f && num2 < 2f)
						{
							state.RestOffset = ((state.RestOffset < 0f) ? num2 : Mathf.Lerp(state.RestOffset, num2, 0.1f));
						}
					}
					if (state.Hovering)
					{
						FrontGrounded.Invoke(__instance) = true;
						BackGrounded.Invoke(__instance) = true;
					}
				}
				catch (Exception e)
				{
					Suppressed.Report("ItemVehicle.PerformGroundCheck (hover)", e);
				}
			}
		}

		[HarmonyPatch(typeof(ItemVehicle), "FixedUpdate")]
		internal static class FixedUpdatePatch
		{
			private static void Postfix(ItemVehicle __instance)
			{
				try
				{
					if (SemiFunc.IsMasterClientOrSingleplayer() && IsHoverVehicle(__instance))
					{
						Rigidbody rb = __instance.rb;
						if (Object.op_Implicit((Object)(object)rb) && !rb.isKinematic && (SemiFunc.RunIsLevel() || SemiFunc.RunIsShop() || SemiFunc.RunIsLobby()))
						{
							Step(__instance, rb, Get(__instance));
						}
					}
				}
				catch (Exception e)
				{
					Suppressed.Report("ItemVehicle.FixedUpdate (hover)", e);
				}
			}
		}

		internal static bool HoverHauler = true;

		internal static bool HoverScout = true;

		internal static float DefaultHeight = 0.5f;

		internal static float MinHeight = 0.25f;

		internal static float MaxHeight = 4f;

		internal static float ClimbSpeed = 2f;

		private const byte EventCode = 164;

		private const string Tag = "RW.Hover";

		private const float StepDown = 0.6f;

		private const float DescendSpeed = 2f;

		private const float CeilingClearance = 1.2f;

		private const float Stiffness = 4f;

		private const float MaxRise = 5f;

		private const float MaxSink = 4f;

		private const float SettleSpeed = 2.5f;

		private const float ProbeRadius = 0.35f;

		private const float InputTimeout = 0.6f;

		private const float PitDepth = 3f;

		private const float UprightTurnSpeed = 360f;

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

		private static int _floorMask = -1;

		private static bool _subscribed;

		private static bool _loggedHover;

		private static FieldRef<ItemVehicle, bool> _frontGrounded;

		private static FieldRef<ItemVehicle, bool> _backGrounded;

		private static int _lastSent;

		private static float _lastSendTime;

		private static int _lastVehicleView = -1;

		private static FieldRef<ItemVehicle, bool> FrontGrounded => _frontGrounded ?? (_frontGrounded = AccessTools.FieldRefAccess<ItemVehicle, bool>("isFrontGrounded"));

		private static FieldRef<ItemVehicle, bool> BackGrounded => _backGrounded ?? (_backGrounded = AccessTools.FieldRefAccess<ItemVehicle, bool>("isBackGrounded"));

		private static int FloorMask
		{
			get
			{
				if (_floorMask == -1)
				{
					return _floorMask = LayerMask.GetMask(new string[1] { "Default" });
				}
				return _floorMask;
			}
		}

		internal static bool IsHoverVehicle(ItemVehicle vehicle)
		{
			if (!Object.op_Implicit((Object)(object)vehicle))
			{
				return false;
			}
			string name = ((Object)vehicle).name;
			if (name.IndexOf("Semiscooter Small", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return HoverScout;
			}
			if (HoverHauler)
			{
				return name.IndexOf("Semiscooter", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		internal static bool IsHaulerOrScout(ItemVehicle vehicle)
		{
			if (Object.op_Implicit((Object)(object)vehicle))
			{
				return ((Object)vehicle).name.IndexOf("Semiscooter", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static PlayerAvatar Driver(ItemVehicle vehicle)
		{
			if (vehicle.seats == null || vehicle.seats.Length == 0)
			{
				return null;
			}
			return vehicle.seats[0].seatedPlayer;
		}

		private static State Get(ItemVehicle vehicle)
		{
			int instanceID = ((Object)vehicle).GetInstanceID();
			if (!States.TryGetValue(instanceID, out var value))
			{
				value = new State();
				States[instanceID] = value;
			}
			return value;
		}

		private static void Step(ItemVehicle vehicle, Rigidbody rb, State state)
		{
			//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_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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Invalid comparison between Unknown and I4
			//IL_0015: 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_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0366: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: Unknown result type (might be due to invalid IL or missing references)
			//IL_037d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			float fixedDeltaTime = Time.fixedDeltaTime;
			Vector3 worldCenterOfMass = rb.worldCenterOfMass;
			if (state.HasFloor)
			{
				Vector3 val = worldCenterOfMass - state.LastPos;
				if (((Vector3)(ref val)).sqrMagnitude > 25f)
				{
					state.HasFloor = false;
				}
			}
			state.LastPos = worldCenterOfMass;
			PlayerAvatar val2 = Driver(vehicle);
			bool flag = (int)vehicle.currentState == 1 && Object.op_Implicit((Object)(object)val2);
			int num = 0;
			if (flag && Time.time - state.InputTime <= 0.6f)
			{
				num = state.Input;
			}
			float num2 = ((state.RestOffset > 0f) ? state.RestOffset : 0.6f);
			float groundY;
			bool flag2 = Probe(vehicle, worldCenterOfMass, out groundY);
			bool flag3 = state.HasFloor && (!flag2 || groundY < state.FloorY - 0.6f);
			if (flag2 && !flag3)
			{
				state.FloorY = groundY;
				state.HasFloor = true;
			}
			else if (state.HasFloor && flag && num < 0 && state.Height <= MinHeight + 0.01f)
			{
				float num3 = state.FloorY - 2f * fixedDeltaTime;
				state.FloorY = (flag2 ? Mathf.Max(num3, groundY) : num3);
			}
			Upright(vehicle, rb, state, flag || !GrabbedByOthers(vehicle), fixedDeltaTime);
			if (!state.HasFloor)
			{
				state.Hovering = false;
				return;
			}
			if (flag)
			{
				if (state.Height < 0f)
				{
					state.Height = DefaultHeight;
				}
				state.Height = Mathf.Clamp(state.Height + (float)num * ClimbSpeed * fixedDeltaTime, MinHeight, Mathf.Max(MinHeight, MaxHeight));
				float num4 = state.FloorY + num2 + state.Height;
				RaycastHit val3 = default(RaycastHit);
				if (Physics.Raycast(worldCenterOfMass, Vector3.up, ref val3, state.Height + num2 + 4f, FloorMask, (QueryTriggerInteraction)1) && !((Component)((RaycastHit)(ref val3)).collider).transform.IsChildOf(((Component)vehicle).transform))
				{
					num4 = Mathf.Min(num4, ((RaycastHit)(ref val3)).point.y - 1.2f);
				}
				HoldHeight(rb, worldCenterOfMass.y, num4, 5f, 4f, fixedDeltaTime);
				if (!state.Hovering && !_loggedHover)
				{
					_loggedHover = true;
					Plugin.Log.LogInfo((object)$"[Hover] {((Object)vehicle).name} is hovering (resting height {num2:0.00} m, hover height {state.Height:0.00} m).");
				}
				state.Hovering = true;
				state.WasDriving = true;
				return;
			}
			state.Hovering = false;
			state.Height = -1f;
			float num5 = state.FloorY + num2;
			bool flag4 = !flag2 || groundY < state.FloorY - 3f;
			if (state.WasDriving)
			{
				state.WasDriving = false;
				Plugin.Log.LogInfo((object)($"[Hover] Driver got out {worldCenterOfMass.y - (flag2 ? groundY : state.FloorY) - num2:0.0} m up; " + (flag4 ? "over a hole, so it stays floating at floor height." : "settling to the ground.")));
			}
			if (flag3 && !flag4)
			{
				state.FloorY = groundY;
				num5 = groundY + num2;
			}
			if (flag4 && worldCenterOfMass.y <= num5 + 0.05f)
			{
				if (!state.LoggedHole)
				{
					state.LoggedHole = true;
					Plugin.Log.LogInfo((object)"[Hover] Kept a parked vehicle from falling into a hole.");
				}
				HoldHeight(rb, worldCenterOfMass.y, num5, 5f, 4f, fixedDeltaTime);
				return;
			}
			state.LoggedHole = false;
			if (worldCenterOfMass.y > num5 + 0.1f)
			{
				rb.WakeUp();
				if (rb.velocity.y < -2.5f)
				{
					HoldVerticalSpeed(rb, -2.5f, fixedDeltaTime);
				}
			}
		}

		private static void Upright(ItemVehicle vehicle, Rigidbody rb, State state, bool on, float dt)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			if (!on)
			{
				if (state.Locked)
				{
					rb.constraints = state.SavedConstraints;
					state.Locked = false;
				}
				return;
			}
			if (!state.Locked)
			{
				state.SavedConstraints = rb.constraints;
				state.Locked = true;
			}
			rb.constraints = (RigidbodyConstraints)(state.SavedConstraints | 0x10 | 0x40);
			Quaternion rotation = rb.rotation;
			Vector3 val = rotation * Vector3.forward;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude < 0.01f)
			{
				val = rotation * (Vector3.up * (0f - Mathf.Sign((rotation * Vector3.forward).y)));
				val.y = 0f;
			}
			if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f))
			{
				Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
				if (Quaternion.Angle(rotation, val2) > 0.2f)
				{
					rb.MoveRotation(Quaternion.RotateTowards(rotation, val2, 360f * dt));
				}
				Vector3 angularVelocity = rb.angularVelocity;
				rb.angularVelocity = new Vector3(0f, angularVelocity.y, 0f);
			}
		}

		private static bool GrabbedByOthers(ItemVehicle vehicle)
		{
			PhysGrabObject component = ((Component)vehicle).GetComponent<PhysGrabObject>();
			if (!Object.op_Implicit((Object)(object)component) || component.playerGrabbing == null)
			{
				return false;
			}
			foreach (PhysGrabber item in component.playerGrabbing)
			{
				if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)item.playerAvatar))
				{
					continue;
				}
				bool flag = false;
				if (vehicle.seats != null)
				{
					VehicleSeat[] seats = vehicle.seats;
					foreach (VehicleSeat val in seats)
					{
						if (val != null && (Object)(object)val.seatedPlayer == (Object)(object)item.playerAvatar)
						{
							flag = true;
							break;
						}
					}
				}
				if (!flag)
				{
					return true;
				}
			}
			return false;
		}

		private static bool Probe(ItemVehicle vehicle, Vector3 from, out float groundY)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			groundY = 0f;
			float num = float.MaxValue;
			RaycastHit[] array = Physics.SphereCastAll(from + Vector3.up * 0.2f, 0.35f, Vector3.down, MaxHeight + 6f, FloorMask, (QueryTriggerInteraction)1);
			for (int i = 0; i < array.Length; i++)
			{
				RaycastHit val = array[i];
				if (!(((RaycastHit)(ref val)).distance <= 0f) && Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider) && !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)vehicle).transform) && !(((RaycastHit)(ref val)).distance >= num))
				{
					num = ((RaycastHit)(ref val)).distance;
					groundY = ((RaycastHit)(ref val)).point.y;
				}
			}
			return num < float.MaxValue;
		}

		private static void HoldHeight(Rigidbody rb, float y, float targetY, float maxRise, float maxSink, float dt)
		{
			HoldVerticalSpeed(rb, Mathf.Clamp((targetY - y) * 4f, 0f - maxSink, maxRise), dt);
		}

		private static void HoldVerticalSpeed(Rigidbody rb, float wantedVy, float dt)
		{
			//IL_000f: 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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			float num = (rb.useGravity ? Physics.gravity.y : 0f);
			float num2 = rb.GetAccumulatedForce().y / Mathf.Max(rb.mass, 0.01f);
			float num3 = rb.velocity.y + (num2 + num) * dt;
			rb.AddForce(Vector3.up * (wantedVy - num3), (ForceMode)2);
		}

		internal static void LocalDriverUpdate()
		{
			try
			{
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					Subscribe();
				}
				PlayerAvatar instance = PlayerAvatar.instance;
				ItemVehicle val = (Object.op_Implicit((Object)(object)instance) ? ItemVehicle.GetVehicleForPlayer(instance) : null);
				if (!Object.op_Implicit((Object)(object)val) || !IsHoverVehicle(val) || (Object)(object)Driver(val) != (Object)(object)instance || !Object.op_Implicit((Object)(object)((Component)val).GetComponent<PhotonView>()))
				{
					if (_lastSent != 0 && _lastVehicleView != -1)
					{
						Send(_lastVehicleView, 0);
					}
					return;
				}
				int num = (SemiFunc.InputHold((InputKey)1) ? 1 : 0) - (SemiFunc.InputHold((InputKey)12) ? 1 : 0);
				if (SemiFunc.IsMasterClientOrSingleplayer())
				{
					State state = Get(val);
					state.Input = num;
					state.InputTime = Time.time;
					return;
				}
				int viewID = ((Component)val).GetComponent<PhotonView>().ViewID;
				if (num != _lastSent || viewID != _lastVehicleView || (num != 0 && Time.time - _lastSendTime > 0.25f))
				{
					Send(viewID, num);
				}
			}
			catch (Exception e)
			{
				Suppressed.Report("Hover driver input", e);
			}
		}

		private static void Send(int view, int input)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0059: Expected O, but got Unknown
			_lastSent = input;
			_lastVehicleView = view;
			_lastSendTime = Time.time;
			if (PhotonNetwork.InRoom)
			{
				PhotonNetwork.RaiseEvent((byte)164, (object)new object[3] { "RW.Hover", view, input }, new RaiseEventOptions
				{
					Receivers = (ReceiverGroup)2
				}, SendOptions.SendReliable);
			}
		}

		private static void Subscribe()
		{
			if (!_subscribed && PhotonNetwork.NetworkingClient != null)
			{
				PhotonNetwork.NetworkingClient.EventReceived += OnEvent;
				_subscribed = true;
			}
		}

		private static void OnEvent(EventData ev)
		{
			try
			{
				if (ev.Code == 164 && PhotonNetwork.IsMasterClient && ev.CustomData is object[] array && array.Length == 3 && array[0] is string text && !(text != "RW.Hover") && array[1] is int num && array[2] is int num2)
				{
					PhotonView val = PhotonView.Find(num);
					ItemVehicle val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<ItemVehicle>() : null);
					PlayerAvatar val3 = (Object.op_Implicit((Object)(object)val2) ? Driver(val2) : null);
					if (Object.op_Implicit((Object)(object)val3) && Object.op_Implicit((Object)(object)val3.photonView) && val3.photonView.Owner != null && val3.photonView.Owner.ActorNumber == ev.Sender)
					{
						State state = Get(val2);
						state.Input = Mathf.Clamp(num2, -1, 1);
						state.InputTime = Time.time;
					}
				}
			}
			catch (Exception e)
			{
				Suppressed.Report("Hover input event", e);
			}
		}
	}
	internal static class Indestructible
	{
		[HarmonyPatch(typeof(ItemVehicle), "ApplyEnemyHitDurabilityLoss")]
		internal static class EnemyHitPatch
		{
			private static bool Prefix(ItemVehicle __instance)
			{
				try
				{
					return !Applies(__instance);
				}
				catch (Exception e)
				{
					Suppressed.Report("ItemVehicle.ApplyEnemyHitDurabilityLoss (indestructible)", e);
					return true;
				}
			}
		}

		[HarmonyPatch(typeof(ItemVehicle), "UpdateImpactDetection")]
		internal static class ImpactPatch
		{
			private static void Postfix(ItemVehicle __instance)
			{
				try
				{
					if (Applies(__instance))
					{
						Guard(__instance);
					}
				}
				catch (Exception e)
				{
					Suppressed.Report("ItemVehicle.UpdateImpactDetection (indestructible)", e);
				}
			}
		}

		[HarmonyPatch(typeof(ItemVehicle), "Update")]
		internal static class UpdatePatch
		{
			private static void Postfix(ItemVehicle __instance)
			{
				try
				{
					if (Applies(__instance))
					{
						Guard(__instance);
					}
				}
				catch (Exception e)
				{
					Suppressed.Report("ItemVehicle.Update (indestructible)", e);
				}
			}
		}

		internal static bool Enabled = true;

		private static readonly Dictionary<int, float> Kept = new Dictionary<int, float>();

		private static readonly Dictionary<int, ItemBattery> Batteries = new Dictionary<int, ItemBattery>();

		private static bool _logged;

		private static bool Applies(ItemVehicle vehicle)
		{
			if (Enabled)
			{
				return Hover.IsHaulerOrScout(vehicle);
			}
			return false;
		}

		private static void Guard(ItemVehicle vehicle)
		{
			int instanceID = ((Object)vehicle).GetInstanceID();
			if (!Batteries.TryGetValue(instanceID, out var value))
			{
				value = ((Component)vehicle).GetComponent<ItemBattery>();
				Batteries[instanceID] = value;
			}
			if (!Object.op_Implicit((Object)(object)value))
			{
				return;
			}
			if (Kept.TryGetValue(instanceID, out var value2) && value.batteryLife < value2)
			{
				value.batteryLife = value2;
				if (!_logged)
				{
					_logged = true;
					Plugin.Log.LogInfo((object)("[Indestructible] Blocked damage to " + ((Object)vehicle).name + "."));
				}
			}
			else
			{
				Kept[instanceID] = value.batteryLife;
			}
		}
	}
	[BepInPlugin("ricketywrecked.repo.hoverhauler", "Hover Hauler", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "ricketywrecked.repo.hoverhauler";

		internal static ManualLogSource Log;

		private void Awake()
		{
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Hover.HoverHauler = ((BaseUnityPlugin)this).Config.Bind<bool>("Vehicles", "Hauler", true, "The Hauler hovers. Restart the game after changing.").Value;
			Hover.HoverScout = ((BaseUnityPlugin)this).Config.Bind<bool>("Vehicles", "Scout", true, "The Scout (small Hauler) hovers. Restart the game after changing.").Value;
			Indestructible.Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Vehicles", "Indestructible", true, "The Hauler and Scout never lose battery bars (their durability) from crashes or enemies, so they can't catch fire or explode. Charging still works. Host setting. Restart the game after changing.").Value;
			Hover.DefaultHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Hover", "DefaultHeight", 0.5f, "Height (metres) above the floor the vehicle hovers at when you get in. Host setting.").Value;
			Hover.MinHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Hover", "MinHeight", 0.25f, "Lowest hover height (metres) when holding Crouch. Host setting.").Value;
			Hover.MaxHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Hover", "MaxHeight", 4f, "Highest hover height (metres) when holding Jump. It also never rises into a ceiling. Host setting.").Value;
			Hover.ClimbSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Hover", "ClimbSpeed", 2f, "How fast (metres per second) Jump and Crouch change the height. Host setting.").Value;
			Harmony val = new Harmony("ricketywrecked.repo.hoverhauler");
			int num = 0;
			int num2 = 0;
			foreach (Type item in new List<Type>
			{
				typeof(Hover.GroundCheckPatch),
				typeof(Hover.FixedUpdatePatch),
				typeof(Indestructible.EnemyHitPatch),
				typeof(Indestructible.ImpactPatch),
				typeof(Indestructible.UpdatePatch)
			})
			{
				try
				{
					val.CreateClassProcessor(item).Patch();
					num++;
				}
				catch (Exception ex)
				{
					num2++;
					Log.LogError((object)("Could not apply " + item.Name + ": " + ex.Message));
				}
			}
			Log.LogInfo((object)string.Format("Hover Hauler loaded: {0} patches applied, {1} failed (Hauler {2}, Scout {3}, indestructible {4}).", num, num2, Hover.HoverHauler ? "on" : "off", Hover.HoverScout ? "on" : "off", Indestructible.Enabled ? "on" : "off"));
		}

		private void Update()
		{
			Hover.LocalDriverUpdate();
		}
	}
	internal static class Suppressed
	{
		private static readonly Dictionary<string, int> Counts = new Dictionary<string, int>();

		internal static void Report(string site, Exception e)
		{
			Counts.TryGetValue(site, out var value);
			value = (Counts[site] = value + 1);
			if (value == 1 || value % 1000 == 0)
			{
				Plugin.Log.LogWarning((object)$"Suppressed exception in {site} ({value} so far): {e.GetType().Name}: {e.Message}");
			}
		}
	}
}