Decompiled source of SkateboardSkitching v1.0.0

Skitching_IL2CPP.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Skating;
using Il2CppScheduleOne.Vehicles;
using Il2CppScheduleOne.Vehicles.AI;
using MelonLoader;
using MelonLoader.Preferences;
using Skitching;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::Skitching.Skitching), "Skitching", "1.0", "Jumble", null)]
[assembly: MelonColor]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Skitching_IL2CPP")]
[assembly: AssemblyConfiguration("Debug_IL2CPP")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Skitching_IL2CPP")]
[assembly: AssemblyTitle("Skitching_IL2CPP")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Skitching;

public static class BuildInfo
{
	public const string Name = "Skitching";

	public const string Description = "Hold onto the back of cars to gain speed on your skateboard.";

	public const string Author = "Jumble";

	public const string Company = null;

	public const string Version = "1.0";

	public const string DownloadLink = null;
}
public static class Config
{
	private static MelonPreferences_Category configCategory;

	private static MelonPreferences_Entry<bool> enabledEntry;

	private static MelonPreferences_Entry<string> skitchKeyEntry;

	private static MelonPreferences_Entry<float> scanIntervalSecondsEntry;

	private static MelonPreferences_Entry<float> attachDistanceEntry;

	private static MelonPreferences_Entry<float> detachDistanceEntry;

	private static MelonPreferences_Entry<float> tetherBackOffsetEntry;

	private static MelonPreferences_Entry<float> tetherUpOffsetEntry;

	private static MelonPreferences_Entry<float> tetherForceEntry;

	private static MelonPreferences_Entry<float> velocityMatchLerpEntry;

	private static MelonPreferences_Entry<float> minVehicleSpeedKmhEntry;

	private static MelonPreferences_Entry<float> npcBoostMinMultiplierEntry;

	private static MelonPreferences_Entry<float> npcBoostMaxMultiplierEntry;

	private static MelonPreferences_Entry<float> npcBoostRampPerSecondEntry;

	public static bool Enabled => enabledEntry?.Value ?? true;

	public static string SkitchKey => skitchKeyEntry?.Value ?? "E";

	public static float ScanIntervalSeconds => scanIntervalSecondsEntry?.Value ?? 0.25f;

	public static float AttachDistance => attachDistanceEntry?.Value ?? 3f;

	public static float DetachDistance => detachDistanceEntry?.Value ?? 7f;

	public static float TetherBackOffset => tetherBackOffsetEntry?.Value ?? 1.3f;

	public static float TetherUpOffset => tetherUpOffsetEntry?.Value ?? (-0.15f);

	public static float TetherForce => tetherForceEntry?.Value ?? 35f;

	public static float VelocityMatchLerp => velocityMatchLerpEntry?.Value ?? 0.9f;

	public static float MinVehicleSpeedKmh => minVehicleSpeedKmhEntry?.Value ?? 3f;

	public static float NpcBoostMinMultiplier => npcBoostMinMultiplierEntry?.Value ?? 3f;

	public static float NpcBoostMaxMultiplier => npcBoostMaxMultiplierEntry?.Value ?? 4f;

	public static float NpcBoostRampPerSecond => npcBoostRampPerSecondEntry?.Value ?? 0.35f;

	public static void Load()
	{
		configCategory = MelonPreferences.CreateCategory("Skitching");
		enabledEntry = configCategory.CreateEntry<bool>("enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		skitchKeyEntry = configCategory.CreateEntry<string>("skitchKey", "E", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		scanIntervalSecondsEntry = configCategory.CreateEntry<float>("scanIntervalSeconds", 0.25f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		attachDistanceEntry = configCategory.CreateEntry<float>("attachDistance", 3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		detachDistanceEntry = configCategory.CreateEntry<float>("detachDistance", 7f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		tetherBackOffsetEntry = configCategory.CreateEntry<float>("tetherBackOffset", 1.3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		tetherUpOffsetEntry = configCategory.CreateEntry<float>("tetherUpOffset", -0.15f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		tetherForceEntry = configCategory.CreateEntry<float>("tetherForce", 35f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		velocityMatchLerpEntry = configCategory.CreateEntry<float>("velocityMatchLerp", 0.9f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		minVehicleSpeedKmhEntry = configCategory.CreateEntry<float>("minVehicleSpeedKmh", 3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		npcBoostMinMultiplierEntry = configCategory.CreateEntry<float>("npcBoostMinMultiplier", 3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		npcBoostMaxMultiplierEntry = configCategory.CreateEntry<float>("npcBoostMaxMultiplier", 4f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		npcBoostRampPerSecondEntry = configCategory.CreateEntry<float>("npcBoostRampPerSecond", 0.35f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
	}
}
public class Skitching : MelonMod
{
	[HarmonyPatch(typeof(VehicleAgent), "UpdateSpeed")]
	private static class VehicleAgent_UpdateSpeed_Patch
	{
		private static void Prefix(VehicleAgent __instance)
		{
			CurrentUpdatingAgentPtr = (((Object)(object)__instance != (Object)null) ? ((Il2CppObjectBase)__instance).Pointer : IntPtr.Zero);
			Skitching instance = Instance;
			if (instance == null)
			{
				return;
			}
			instance.TempBoostLog("UpdateSpeed prefix fired for ptr=0x" + CurrentUpdatingAgentPtr.ToString("X"));
			if (instance.TryGetBoostedUnmarkedSpeedForCurrentUpdate(out var boostedUnmarkedSpeed))
			{
				if (boostedUnmarkedSpeed > 25f)
				{
					VehicleAgent.UnmarkedSpeed = boostedUnmarkedSpeed;
					instance.TempBoostLog($"Applied temp UnmarkedSpeed override: 25.00 -> {boostedUnmarkedSpeed:F2}");
				}
				if ((Object)(object)__instance != (Object)null && boostedUnmarkedSpeed > __instance.targetSpeed)
				{
					instance.TempBoostLog($"Raising targetSpeed in prefix: {__instance.targetSpeed:F2} -> {boostedUnmarkedSpeed:F2}");
					__instance.targetSpeed = boostedUnmarkedSpeed;
				}
			}
		}

		private static void Postfix(VehicleAgent __instance)
		{
			Skitching instance = Instance;
			if (instance != null && instance.TryGetBoostedUnmarkedSpeedForCurrentUpdate(out var boostedUnmarkedSpeed) && (Object)(object)__instance != (Object)null && boostedUnmarkedSpeed > __instance.targetSpeed)
			{
				instance.TempBoostLog($"Raising targetSpeed in postfix: {__instance.targetSpeed:F2} -> {boostedUnmarkedSpeed:F2}");
				__instance.targetSpeed = boostedUnmarkedSpeed;
			}
			if (VehicleAgent.UnmarkedSpeed != 25f)
			{
				VehicleAgent.UnmarkedSpeed = 25f;
				instance?.TempBoostLog("Restoring UnmarkedSpeed to 25.00");
			}
			CurrentUpdatingAgentPtr = IntPtr.Zero;
		}
	}

	internal static Skitching Instance;

	internal static IntPtr CurrentUpdatingAgentPtr = IntPtr.Zero;

	private KeyCode _skitchKey = (KeyCode)101;

	private LandVehicle _skitchedVehicle;

	private Rigidbody _skitchedVehicleRb;

	private float _nextVehicleScanTime;

	private float _nextBoostDebugLogTime;

	private float _npcBoostTargetMultiplier = 1f;

	private float _npcBoostCurrentMultiplier = 1f;

	private float _npcBoostBaseSpeedKmh;

	private bool _agentBoostActive;

	private VehicleAgent _boostedAgent;

	public override void OnInitializeMelon()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Config.Load();
		((MelonBase)this).HarmonyInstance.PatchAll();
		if (!Enum.TryParse<KeyCode>(Config.SkitchKey, ignoreCase: true, out _skitchKey))
		{
			MelonLogger.Warning("Invalid skitchKey '" + Config.SkitchKey + "'. Falling back to 'E'.");
			_skitchKey = (KeyCode)101;
		}
	}

	public override void OnUpdate()
	{
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		if (!Config.Enabled)
		{
			return;
		}
		Player local = Player.Local;
		if ((Object)(object)local == (Object)null)
		{
			StopSkitching();
			return;
		}
		Skateboard activeSkateboard = local.ActiveSkateboard;
		if ((Object)(object)activeSkateboard == (Object)null)
		{
			StopSkitching();
		}
		else if ((Object)(object)_skitchedVehicle != (Object)null && _skitchedVehicle.LocalPlayerIsInVehicle)
		{
			StopSkitching();
		}
		else if (!Input.GetKey(_skitchKey))
		{
			StopSkitching();
		}
		else if ((Object)(object)_skitchedVehicle == (Object)null && Time.time >= _nextVehicleScanTime)
		{
			_nextVehicleScanTime = Time.time + Mathf.Max(0.05f, Config.ScanIntervalSeconds);
			TryStartSkitching(local, activeSkateboard);
		}
	}

	public override void OnFixedUpdate()
	{
		//IL_00a4: 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_00dd: 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_00e4: 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_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_00f9: 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_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: 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)
		if (!Config.Enabled || (Object)(object)_skitchedVehicle == (Object)null || (Object)(object)_skitchedVehicleRb == (Object)null)
		{
			return;
		}
		Player local = Player.Local;
		if ((Object)(object)local == (Object)null)
		{
			StopSkitching();
			return;
		}
		Skateboard activeSkateboard = local.ActiveSkateboard;
		if ((Object)(object)activeSkateboard == (Object)null)
		{
			StopSkitching();
			return;
		}
		Rigidbody rb = activeSkateboard.Rb;
		if ((Object)(object)rb == (Object)null)
		{
			StopSkitching();
			return;
		}
		float num = Vector3.Distance(((Component)activeSkateboard).transform.position, ((Component)_skitchedVehicle).transform.position);
		if (num > Config.DetachDistance)
		{
			StopSkitching();
			return;
		}
		Vector3 skitchTargetPosition = GetSkitchTargetPosition(_skitchedVehicle);
		Vector3 val = skitchTargetPosition - ((Component)activeSkateboard).transform.position;
		rb.AddForce(val * Config.TetherForce, (ForceMode)5);
		Vector3 velocity = _skitchedVehicleRb.velocity;
		float num2 = Mathf.Clamp01(Config.VelocityMatchLerp);
		rb.velocity = Vector3.Lerp(rb.velocity, velocity, num2);
		ApplyNpcDriverBoost();
	}

	private void TryStartSkitching(Player player, Skateboard board)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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)
		Il2CppArrayBase<LandVehicle> val = Object.FindObjectsOfType<LandVehicle>();
		if (val == null || val.Length == 0)
		{
			return;
		}
		LandVehicle val2 = null;
		Rigidbody skitchedVehicleRb = null;
		float num = float.MaxValue;
		Vector3 position = ((Component)board).transform.position;
		for (int i = 0; i < val.Length; i++)
		{
			LandVehicle val3 = val[i];
			if ((Object)(object)val3 == (Object)null || val3.isParked || val3.Speed_Kmh < Config.MinVehicleSpeedKmh || val3.LocalPlayerIsInVehicle)
			{
				continue;
			}
			Rigidbody rb = val3.Rb;
			if (!((Object)(object)rb == (Object)null))
			{
				float num2 = Vector3.Distance(position, ((Component)val3).transform.position);
				if (num2 <= Config.AttachDistance && num2 < num)
				{
					num = num2;
					val2 = val3;
					skitchedVehicleRb = rb;
				}
			}
		}
		if (!((Object)(object)val2 == (Object)null))
		{
			_skitchedVehicle = val2;
			_skitchedVehicleRb = skitchedVehicleRb;
			_npcBoostCurrentMultiplier = 1f;
			_npcBoostBaseSpeedKmh = 25f;
			float num3 = Mathf.Max(1f, Config.NpcBoostMinMultiplier);
			float num4 = Mathf.Max(num3, Config.NpcBoostMaxMultiplier);
			_npcBoostTargetMultiplier = Random.Range(num3, num4);
		}
	}

	private static Vector3 GetSkitchTargetPosition(LandVehicle vehicle)
	{
		//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_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: 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_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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_006b: 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_0098: 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_00a1: 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_00bb: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: 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_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)vehicle == (Object)null)
		{
			return Vector3.zero;
		}
		if ((Object)(object)vehicle.boundingBox != (Object)null)
		{
			BoxCollider boundingBox = vehicle.boundingBox;
			Vector3 center = boundingBox.center;
			Vector3 size = boundingBox.size;
			float num = Mathf.Abs(size.z * ((Component)boundingBox).transform.lossyScale.z) * 0.5f;
			float num2 = Mathf.Abs(size.y * ((Component)boundingBox).transform.lossyScale.y) * 0.5f;
			Vector3 val = ((Component)boundingBox).transform.TransformPoint(center);
			return val - ((Component)vehicle).transform.forward * (num + Config.TetherBackOffset) - ((Component)vehicle).transform.up * (num2 * 0.6f) + ((Component)vehicle).transform.up * Config.TetherUpOffset;
		}
		float num3 = 1.5f;
		try
		{
			Vector3 boundingBoxDimensions = vehicle.BoundingBoxDimensions;
			if (boundingBoxDimensions.z > 0.1f)
			{
				num3 = boundingBoxDimensions.z * 0.5f;
			}
		}
		catch
		{
		}
		return ((Component)vehicle).transform.position - ((Component)vehicle).transform.forward * (num3 + Config.TetherBackOffset) + ((Component)vehicle).transform.up * Config.TetherUpOffset;
	}

	private void ApplyNpcDriverBoost()
	{
		if ((Object)(object)_skitchedVehicle == (Object)null || (Object)(object)_skitchedVehicleRb == (Object)null || !_skitchedVehicle.IsOccupied || !((Object)(object)_skitchedVehicle.DriverPlayer == (Object)null))
		{
			return;
		}
		_npcBoostCurrentMultiplier = Mathf.MoveTowards(_npcBoostCurrentMultiplier, _npcBoostTargetMultiplier, Mathf.Max(0.01f, Config.NpcBoostRampPerSecond) * Time.fixedDeltaTime);
		VehicleAgent agent = _skitchedVehicle.Agent;
		if ((Object)(object)agent == (Object)null)
		{
			TempBoostLog("ApplyNpcDriverBoost: vehicle has no agent");
			return;
		}
		if (!_agentBoostActive)
		{
			_boostedAgent = agent;
			_agentBoostActive = true;
		}
		TempBoostLog($"Boost active: mult={_npcBoostCurrentMultiplier:F2}, boostedSpeed={_npcBoostBaseSpeedKmh * _npcBoostCurrentMultiplier:F2} km/h, vehicleSpeed={_skitchedVehicle.Speed_Kmh:F1} km/h");
	}

	private void StopSkitching()
	{
		bool flag = (Object)(object)_skitchedVehicle != (Object)null || (Object)(object)_skitchedVehicleRb != (Object)null || _agentBoostActive || (Object)(object)_boostedAgent != (Object)null;
		_skitchedVehicle = null;
		_skitchedVehicleRb = null;
		_npcBoostCurrentMultiplier = 1f;
		_npcBoostTargetMultiplier = 1f;
		_npcBoostBaseSpeedKmh = 0f;
		_agentBoostActive = false;
		_boostedAgent = null;
		VehicleAgent.UnmarkedSpeed = 25f;
	}

	internal bool TryGetBoostedUnmarkedSpeedForCurrentUpdate(out float boostedUnmarkedSpeed)
	{
		boostedUnmarkedSpeed = 0f;
		if (!_agentBoostActive || (Object)(object)_boostedAgent == (Object)null)
		{
			return false;
		}
		if (CurrentUpdatingAgentPtr == IntPtr.Zero)
		{
			return false;
		}
		if (((Il2CppObjectBase)_boostedAgent).Pointer != CurrentUpdatingAgentPtr)
		{
			return false;
		}
		boostedUnmarkedSpeed = _npcBoostBaseSpeedKmh * _npcBoostCurrentMultiplier;
		return true;
	}

	private void TempBoostLog(string message)
	{
	}
}

Skitching_Mono.dll

Decompiled a day ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using ScheduleOne.PlayerScripts;
using ScheduleOne.Skating;
using ScheduleOne.Vehicles;
using ScheduleOne.Vehicles.AI;
using Skitching;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::Skitching.Skitching), "Skitching", "1.0", "Jumble", null)]
[assembly: MelonColor]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Skitching_Mono")]
[assembly: AssemblyConfiguration("Debug_Mono")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Skitching_Mono")]
[assembly: AssemblyTitle("Skitching_Mono")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Skitching;

public static class BuildInfo
{
	public const string Name = "Skitching";

	public const string Description = "Hold onto the back of cars to gain speed on your skateboard.";

	public const string Author = "Jumble";

	public const string Company = null;

	public const string Version = "1.0";

	public const string DownloadLink = null;
}
public static class Config
{
	private static MelonPreferences_Category configCategory;

	private static MelonPreferences_Entry<bool> enabledEntry;

	private static MelonPreferences_Entry<string> skitchKeyEntry;

	private static MelonPreferences_Entry<float> scanIntervalSecondsEntry;

	private static MelonPreferences_Entry<float> attachDistanceEntry;

	private static MelonPreferences_Entry<float> detachDistanceEntry;

	private static MelonPreferences_Entry<float> tetherBackOffsetEntry;

	private static MelonPreferences_Entry<float> tetherUpOffsetEntry;

	private static MelonPreferences_Entry<float> tetherForceEntry;

	private static MelonPreferences_Entry<float> velocityMatchLerpEntry;

	private static MelonPreferences_Entry<float> minVehicleSpeedKmhEntry;

	private static MelonPreferences_Entry<float> npcBoostMinMultiplierEntry;

	private static MelonPreferences_Entry<float> npcBoostMaxMultiplierEntry;

	private static MelonPreferences_Entry<float> npcBoostRampPerSecondEntry;

	public static bool Enabled => enabledEntry?.Value ?? true;

	public static string SkitchKey => skitchKeyEntry?.Value ?? "E";

	public static float ScanIntervalSeconds => scanIntervalSecondsEntry?.Value ?? 0.25f;

	public static float AttachDistance => attachDistanceEntry?.Value ?? 3f;

	public static float DetachDistance => detachDistanceEntry?.Value ?? 7f;

	public static float TetherBackOffset => tetherBackOffsetEntry?.Value ?? 1.3f;

	public static float TetherUpOffset => tetherUpOffsetEntry?.Value ?? (-0.15f);

	public static float TetherForce => tetherForceEntry?.Value ?? 35f;

	public static float VelocityMatchLerp => velocityMatchLerpEntry?.Value ?? 0.9f;

	public static float MinVehicleSpeedKmh => minVehicleSpeedKmhEntry?.Value ?? 3f;

	public static float NpcBoostMinMultiplier => npcBoostMinMultiplierEntry?.Value ?? 3f;

	public static float NpcBoostMaxMultiplier => npcBoostMaxMultiplierEntry?.Value ?? 4f;

	public static float NpcBoostRampPerSecond => npcBoostRampPerSecondEntry?.Value ?? 0.35f;

	public static void Load()
	{
		configCategory = MelonPreferences.CreateCategory("Skitching");
		enabledEntry = configCategory.CreateEntry<bool>("enabled", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		skitchKeyEntry = configCategory.CreateEntry<string>("skitchKey", "E", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		scanIntervalSecondsEntry = configCategory.CreateEntry<float>("scanIntervalSeconds", 0.25f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		attachDistanceEntry = configCategory.CreateEntry<float>("attachDistance", 3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		detachDistanceEntry = configCategory.CreateEntry<float>("detachDistance", 7f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		tetherBackOffsetEntry = configCategory.CreateEntry<float>("tetherBackOffset", 1.3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		tetherUpOffsetEntry = configCategory.CreateEntry<float>("tetherUpOffset", -0.15f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		tetherForceEntry = configCategory.CreateEntry<float>("tetherForce", 35f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		velocityMatchLerpEntry = configCategory.CreateEntry<float>("velocityMatchLerp", 0.9f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		minVehicleSpeedKmhEntry = configCategory.CreateEntry<float>("minVehicleSpeedKmh", 3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		npcBoostMinMultiplierEntry = configCategory.CreateEntry<float>("npcBoostMinMultiplier", 3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		npcBoostMaxMultiplierEntry = configCategory.CreateEntry<float>("npcBoostMaxMultiplier", 4f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
		npcBoostRampPerSecondEntry = configCategory.CreateEntry<float>("npcBoostRampPerSecond", 0.35f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
	}
}
public class Skitching : MelonMod
{
	[HarmonyPatch(typeof(VehicleAgent), "UpdateSpeed")]
	private static class VehicleAgent_UpdateSpeed_Patch
	{
		private static void Prefix(VehicleAgent __instance)
		{
			CurrentUpdatingAgent = __instance;
			Skitching instance = Instance;
			if (instance == null)
			{
				return;
			}
			instance.TempBoostLog("UpdateSpeed prefix fired for ptr=0x" + CurrentUpdatingAgentPtr.ToString("X"));
			if (!instance.TryGetBoostedUnmarkedSpeedForCurrentUpdate(out var boostedUnmarkedSpeed))
			{
				return;
			}
			if (boostedUnmarkedSpeed > 25f)
			{
				VehicleAgent.UnmarkedSpeed = boostedUnmarkedSpeed;
				instance.TempBoostLog($"Applied temp UnmarkedSpeed override: 25.00 -> {boostedUnmarkedSpeed:F2}");
			}
			if ((Object)(object)__instance != (Object)null)
			{
				float targetSpeed = GetTargetSpeed(__instance);
				if (boostedUnmarkedSpeed > targetSpeed)
				{
					instance.TempBoostLog($"Raising targetSpeed in prefix: {targetSpeed:F2} -> {boostedUnmarkedSpeed:F2}");
					SetTargetSpeed(__instance, boostedUnmarkedSpeed);
				}
			}
		}

		private static void Postfix(VehicleAgent __instance)
		{
			Skitching instance = Instance;
			if (instance != null && instance.TryGetBoostedUnmarkedSpeedForCurrentUpdate(out var boostedUnmarkedSpeed) && (Object)(object)__instance != (Object)null)
			{
				float targetSpeed = GetTargetSpeed(__instance);
				if (boostedUnmarkedSpeed > targetSpeed)
				{
					instance.TempBoostLog($"Raising targetSpeed in postfix: {targetSpeed:F2} -> {boostedUnmarkedSpeed:F2}");
					SetTargetSpeed(__instance, boostedUnmarkedSpeed);
				}
			}
			if (VehicleAgent.UnmarkedSpeed != 25f)
			{
				VehicleAgent.UnmarkedSpeed = 25f;
				instance?.TempBoostLog("Restoring UnmarkedSpeed to 25.00");
			}
			CurrentUpdatingAgentPtr = IntPtr.Zero;
			CurrentUpdatingAgent = null;
		}
	}

	internal static Skitching Instance;

	internal static IntPtr CurrentUpdatingAgentPtr = IntPtr.Zero;

	internal static VehicleAgent CurrentUpdatingAgent;

	private KeyCode _skitchKey = (KeyCode)101;

	private LandVehicle _skitchedVehicle;

	private Rigidbody _skitchedVehicleRb;

	private float _nextVehicleScanTime;

	private float _nextBoostDebugLogTime;

	private float _npcBoostTargetMultiplier = 1f;

	private float _npcBoostCurrentMultiplier = 1f;

	private float _npcBoostBaseSpeedKmh;

	private bool _agentBoostActive;

	private VehicleAgent _boostedAgent;

	public override void OnInitializeMelon()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		Instance = this;
		Config.Load();
		((MelonBase)this).HarmonyInstance.PatchAll();
		if (!Enum.TryParse<KeyCode>(Config.SkitchKey, ignoreCase: true, out _skitchKey))
		{
			MelonLogger.Warning("Invalid skitchKey '" + Config.SkitchKey + "'. Falling back to 'E'.");
			_skitchKey = (KeyCode)101;
		}
	}

	public override void OnUpdate()
	{
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		if (!Config.Enabled)
		{
			return;
		}
		Player local = Player.Local;
		if ((Object)(object)local == (Object)null)
		{
			StopSkitching();
			return;
		}
		Skateboard activeSkateboard = local.ActiveSkateboard;
		if ((Object)(object)activeSkateboard == (Object)null)
		{
			StopSkitching();
		}
		else if ((Object)(object)_skitchedVehicle != (Object)null && _skitchedVehicle.LocalPlayerIsInVehicle)
		{
			StopSkitching();
		}
		else if (!Input.GetKey(_skitchKey))
		{
			StopSkitching();
		}
		else if ((Object)(object)_skitchedVehicle == (Object)null && Time.time >= _nextVehicleScanTime)
		{
			_nextVehicleScanTime = Time.time + Mathf.Max(0.05f, Config.ScanIntervalSeconds);
			TryStartSkitching(local, activeSkateboard);
		}
	}

	public override void OnFixedUpdate()
	{
		//IL_00a4: 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_00dd: 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_00e4: 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_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_00f9: 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_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: 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)
		if (!Config.Enabled || (Object)(object)_skitchedVehicle == (Object)null || (Object)(object)_skitchedVehicleRb == (Object)null)
		{
			return;
		}
		Player local = Player.Local;
		if ((Object)(object)local == (Object)null)
		{
			StopSkitching();
			return;
		}
		Skateboard activeSkateboard = local.ActiveSkateboard;
		if ((Object)(object)activeSkateboard == (Object)null)
		{
			StopSkitching();
			return;
		}
		Rigidbody rb = activeSkateboard.Rb;
		if ((Object)(object)rb == (Object)null)
		{
			StopSkitching();
			return;
		}
		float num = Vector3.Distance(((Component)activeSkateboard).transform.position, ((Component)_skitchedVehicle).transform.position);
		if (num > Config.DetachDistance)
		{
			StopSkitching();
			return;
		}
		Vector3 skitchTargetPosition = GetSkitchTargetPosition(_skitchedVehicle);
		Vector3 val = skitchTargetPosition - ((Component)activeSkateboard).transform.position;
		rb.AddForce(val * Config.TetherForce, (ForceMode)5);
		Vector3 velocity = _skitchedVehicleRb.velocity;
		float num2 = Mathf.Clamp01(Config.VelocityMatchLerp);
		rb.velocity = Vector3.Lerp(rb.velocity, velocity, num2);
		ApplyNpcDriverBoost();
	}

	private void TryStartSkitching(Player player, Skateboard board)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: 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)
		LandVehicle[] array = Object.FindObjectsOfType<LandVehicle>();
		if (array == null || array.Length == 0)
		{
			return;
		}
		LandVehicle val = null;
		Rigidbody skitchedVehicleRb = null;
		float num = float.MaxValue;
		Vector3 position = ((Component)board).transform.position;
		foreach (LandVehicle val2 in array)
		{
			if ((Object)(object)val2 == (Object)null || val2.isParked || val2.Speed_Kmh < Config.MinVehicleSpeedKmh || val2.LocalPlayerIsInVehicle)
			{
				continue;
			}
			Rigidbody rb = val2.Rb;
			if (!((Object)(object)rb == (Object)null))
			{
				float num2 = Vector3.Distance(position, ((Component)val2).transform.position);
				if (num2 <= Config.AttachDistance && num2 < num)
				{
					num = num2;
					val = val2;
					skitchedVehicleRb = rb;
				}
			}
		}
		if (!((Object)(object)val == (Object)null))
		{
			_skitchedVehicle = val;
			_skitchedVehicleRb = skitchedVehicleRb;
			_npcBoostCurrentMultiplier = 1f;
			_npcBoostBaseSpeedKmh = 25f;
			float num3 = Mathf.Max(1f, Config.NpcBoostMinMultiplier);
			float num4 = Mathf.Max(num3, Config.NpcBoostMaxMultiplier);
			_npcBoostTargetMultiplier = Random.Range(num3, num4);
		}
	}

	private static Vector3 GetSkitchTargetPosition(LandVehicle vehicle)
	{
		//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_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: Unknown result type (might be due to invalid IL or missing references)
		//IL_0155: Unknown result type (might be due to invalid IL or missing references)
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: 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_0174: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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_006b: 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_0098: 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_00a1: 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_00bb: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: 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_0102: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)vehicle == (Object)null)
		{
			return Vector3.zero;
		}
		if ((Object)(object)vehicle.boundingBox != (Object)null)
		{
			BoxCollider boundingBox = vehicle.boundingBox;
			Vector3 center = boundingBox.center;
			Vector3 size = boundingBox.size;
			float num = Mathf.Abs(size.z * ((Component)boundingBox).transform.lossyScale.z) * 0.5f;
			float num2 = Mathf.Abs(size.y * ((Component)boundingBox).transform.lossyScale.y) * 0.5f;
			Vector3 val = ((Component)boundingBox).transform.TransformPoint(center);
			return val - ((Component)vehicle).transform.forward * (num + Config.TetherBackOffset) - ((Component)vehicle).transform.up * (num2 * 0.6f) + ((Component)vehicle).transform.up * Config.TetherUpOffset;
		}
		float num3 = 1.5f;
		try
		{
			Vector3 boundingBoxDimensions = vehicle.BoundingBoxDimensions;
			if (boundingBoxDimensions.z > 0.1f)
			{
				num3 = boundingBoxDimensions.z * 0.5f;
			}
		}
		catch
		{
		}
		return ((Component)vehicle).transform.position - ((Component)vehicle).transform.forward * (num3 + Config.TetherBackOffset) + ((Component)vehicle).transform.up * Config.TetherUpOffset;
	}

	private void ApplyNpcDriverBoost()
	{
		if ((Object)(object)_skitchedVehicle == (Object)null || (Object)(object)_skitchedVehicleRb == (Object)null || !_skitchedVehicle.IsOccupied || !((Object)(object)_skitchedVehicle.DriverPlayer == (Object)null))
		{
			return;
		}
		_npcBoostCurrentMultiplier = Mathf.MoveTowards(_npcBoostCurrentMultiplier, _npcBoostTargetMultiplier, Mathf.Max(0.01f, Config.NpcBoostRampPerSecond) * Time.fixedDeltaTime);
		VehicleAgent agent = _skitchedVehicle.Agent;
		if ((Object)(object)agent == (Object)null)
		{
			TempBoostLog("ApplyNpcDriverBoost: vehicle has no agent");
			return;
		}
		if (!_agentBoostActive)
		{
			_boostedAgent = agent;
			_agentBoostActive = true;
		}
		TempBoostLog($"Boost active: mult={_npcBoostCurrentMultiplier:F2}, boostedSpeed={_npcBoostBaseSpeedKmh * _npcBoostCurrentMultiplier:F2} km/h, vehicleSpeed={_skitchedVehicle.Speed_Kmh:F1} km/h");
	}

	private void StopSkitching()
	{
		bool flag = (Object)(object)_skitchedVehicle != (Object)null || (Object)(object)_skitchedVehicleRb != (Object)null || _agentBoostActive || (Object)(object)_boostedAgent != (Object)null;
		_skitchedVehicle = null;
		_skitchedVehicleRb = null;
		_npcBoostCurrentMultiplier = 1f;
		_npcBoostTargetMultiplier = 1f;
		_npcBoostBaseSpeedKmh = 0f;
		_agentBoostActive = false;
		_boostedAgent = null;
		VehicleAgent.UnmarkedSpeed = 25f;
	}

	internal bool TryGetBoostedUnmarkedSpeedForCurrentUpdate(out float boostedUnmarkedSpeed)
	{
		boostedUnmarkedSpeed = 0f;
		if (!_agentBoostActive || (Object)(object)_boostedAgent == (Object)null)
		{
			return false;
		}
		if ((Object)(object)CurrentUpdatingAgent == (Object)null)
		{
			return false;
		}
		if (_boostedAgent != CurrentUpdatingAgent)
		{
			return false;
		}
		boostedUnmarkedSpeed = _npcBoostBaseSpeedKmh * _npcBoostCurrentMultiplier;
		return true;
	}

	private static float GetTargetSpeed(VehicleAgent agent)
	{
		FieldInfo fieldInfo = AccessTools.Field(typeof(VehicleAgent), "targetSpeed");
		if (fieldInfo == null)
		{
			return 0f;
		}
		return (fieldInfo.GetValue(agent) is float num) ? num : 0f;
	}

	private static void SetTargetSpeed(VehicleAgent agent, float value)
	{
		AccessTools.Field(typeof(VehicleAgent), "targetSpeed")?.SetValue(agent, value);
	}

	private void TempBoostLog(string message)
	{
	}
}