Decompiled source of HardcoreAI v1.1.0

HardcorePolice.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HardcorePolice;
using HarmonyLib;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Police;
using Il2CppScheduleOne.Vision;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using MelonLoader.Utils;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("A hardcore police mod for Schedule I")]
[assembly: AssemblyDescription("A hardcore police mod for Schedule I")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HardcorePolice")]
[assembly: AssemblyCopyright("Created by Babyhamsta")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: MelonColor]
[assembly: MelonInfo(typeof(Main), "HardcorePolice", "1.1.0", "Babyhamsta", null)]
[assembly: MelonGame(null, null)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace HardcorePolice;

public class ModConfig
{
	public bool ExtendedVision = true;

	public bool SpeedBoost = true;

	public bool DistanceSpeedBoost = true;

	public bool Flanking = true;

	public bool ArrestAdjustments = true;

	public bool RadioNearby = true;

	public bool FasterDetection;

	public float VisionRangeMultiplier = 5f;

	public float VisionHorizontalFOV = 165f;

	public float VisionVerticalFOV = 80f;

	public float SpeedBoostMultiplier = 1.3f;

	public float MovementSpeedScale = 1.15f;

	public float MoveSpeedMultiplier = 1.15f;

	public float DistanceBoostBase = 1.45f;

	public float DistanceBoostMax = 2f;

	public float DistanceMax = 100f;

	public float FlankUpdateCooldown = 3f;

	public float ArrestCooldownCircleDistance = 5f;

	public float ArrestProgressSpeed = 1.5f;

	public float RadioDistance = 100f;
}
public class Main : MelonMod
{
	private static ModConfig config;

	private static string configPath;

	private static Harmony harmony;

	private static readonly HashSet<IntPtr> boostedNpcs = new HashSet<IntPtr>();

	private static readonly Dictionary<IntPtr, float> stuckTimers = new Dictionary<IntPtr, float>();

	private static readonly Dictionary<IntPtr, float> lastSpeedMultiplier = new Dictionary<IntPtr, float>();

	private static readonly Dictionary<IntPtr, float> lastSpeedUpdateTime = new Dictionary<IntPtr, float>();

	private static readonly Dictionary<IntPtr, string> officerRoles = new Dictionary<IntPtr, string>();

	private static readonly Dictionary<IntPtr, Vector3> lastAssignedIntercept = new Dictionary<IntPtr, Vector3>();

	private static readonly Dictionary<IntPtr, float> flankTimers = new Dictionary<IntPtr, float>();

	private static bool RadioedOfficers = false;

	private static void LoadConfig()
	{
		configPath = Path.Combine(MelonEnvironment.UserDataDirectory, "HardcorePoliceConfig.json");
		if (File.Exists(configPath))
		{
			try
			{
				config = JsonConvert.DeserializeObject<ModConfig>(File.ReadAllText(configPath));
				MelonLogger.Msg("[Hardcore Police] Config loaded.");
				return;
			}
			catch (Exception ex)
			{
				MelonLogger.Warning("[Hardcore Police] Failed to parse config: " + ex.Message + ". Recreating default config.");
				return;
			}
		}
		config = new ModConfig();
		SaveConfig();
		MelonLogger.Msg("[Hardcore Police] Default config created.");
	}

	private static void SaveConfig()
	{
		string contents = JsonConvert.SerializeObject((object)config, (Formatting)1);
		File.WriteAllText(configPath, contents);
	}

	public override void OnInitializeMelon()
	{
		MelonLogger.Msg("[Hardcore Police] Loaded version v1.1.0");
		LoadConfig();
	}

	public override void OnSceneWasInitialized(int buildIndex, string sceneName)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Expected O, but got Unknown
		if (sceneName == "Main")
		{
			harmony = new Harmony("HardcorePolice.Patches");
			Patch(harmony, typeof(NPCMovement), "UpdateDestination", "UpdateDestination_Postfix");
			Patch(harmony, typeof(PoliceOfficer), "Activate", "VisionCone_Postfix");
			Patch(harmony, typeof(PursuitBehaviour), "UpdateArrest", "UpdateArrest_Postfix");
			Patch(harmony, typeof(PursuitBehaviour), "Begin", "OnPursuitBegin_Postfix");
			Patch(harmony, typeof(PursuitBehaviour), "Stop", "OnPursuitEnd_Postfix");
			Patch(harmony, typeof(PlayerCrimeData), "SetPursuitLevel", "OnPursuitTimeout_Postfix");
			MelonLogger.Msg("[HardcorePolice] Harmony patches applied in Main scene.");
		}
	}

	public override void OnSceneWasUnloaded(int buildIndex, string sceneName)
	{
		if (sceneName == "Main")
		{
			harmony.UnpatchSelf();
			boostedNpcs.Clear();
			stuckTimers.Clear();
			lastSpeedMultiplier.Clear();
			lastSpeedUpdateTime.Clear();
			officerRoles.Clear();
			lastAssignedIntercept.Clear();
			flankTimers.Clear();
			RadioedOfficers = false;
			MelonLogger.Msg("[Hardcore Police] Main scene unloaded. Resetting state.");
		}
	}

	private static void Patch(Harmony harmony, Type targetType, string methodName, string hookMethod)
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: Expected O, but got Unknown
		MethodInfo method = targetType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		MethodInfo method2 = typeof(Main).GetMethod(hookMethod, BindingFlags.Static | BindingFlags.NonPublic);
		if (method == null || method2 == null)
		{
			MelonLogger.Error("[Hardcore Police] Failed to patch " + targetType.Name + "." + methodName);
			return;
		}
		harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		MelonLogger.Msg("[Hardcore Police] Patched " + targetType.Name + "." + methodName);
	}

	private static void UpdateDestination_Postfix(NPCMovement __instance)
	{
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
		if (!config.Flanking || (Object)(object)__instance == (Object)null || (Object)(object)__instance.Agent == (Object)null || !((Behaviour)__instance.Agent).enabled)
		{
			return;
		}
		NPC npc = __instance.npc;
		if ((Object)(object)npc == (Object)null || !(npc is PoliceOfficer))
		{
			return;
		}
		IntPtr pointer = ((Il2CppObjectBase)npc).Pointer;
		Vector3 currentDestination = __instance.CurrentDestination;
		float num = Vector3.Distance(__instance.FootPosition, currentDestination);
		if (!__instance.Agent.pathPending && !__instance.Agent.hasPath && num > 10f)
		{
			if (!stuckTimers.ContainsKey(pointer))
			{
				stuckTimers[pointer] = 0f;
			}
			stuckTimers[pointer] += Time.deltaTime;
			if (stuckTimers[pointer] > 0.25f)
			{
				__instance.Agent.ResetPath();
				__instance.Agent.SetDestination(currentDestination);
				stuckTimers[pointer] = 0f;
			}
		}
		else
		{
			stuckTimers[pointer] = 0f;
		}
	}

	private static void VisionCone_Postfix(PoliceOfficer __instance)
	{
		if (!config.ExtendedVision || (Object)(object)__instance == (Object)null || (Object)(object)((NPC)__instance).awareness == (Object)null || (Object)(object)((NPC)__instance).awareness.VisionCone == (Object)null)
		{
			return;
		}
		VisionCone visionCone = ((NPC)__instance).awareness.VisionCone;
		visionCone.RangeMultiplier = config.VisionRangeMultiplier;
		visionCone.HorizontalFOV = config.VisionHorizontalFOV;
		visionCone.VerticalFOV = config.VisionVerticalFOV;
		if (config.FasterDetection)
		{
			Enumerator<Player, Dictionary<EVisualState, StateContainer>> enumerator = visionCone.StateSettings.Values.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Enumerator<EVisualState, StateContainer> enumerator2 = enumerator.Current.Values.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					StateContainer current = enumerator2.Current;
					current.RequiredNoticeTime = Mathf.Max(0.25f, current.RequiredNoticeTime * 0.5f);
				}
			}
		}
		MelonLogger.Msg("[Hardcore Police] Adjusted VisionCone for " + ((NPC)__instance).ID);
	}

	private static void OnPursuitBegin_Postfix(PursuitBehaviour __instance)
	{
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
		ApplySpeedBoostOnce(__instance);
		IntPtr pointer = ((Il2CppObjectBase)((Behaviour)__instance).Npc).Pointer;
		if (config.Flanking && !officerRoles.ContainsKey(pointer))
		{
			Vector3 position = ((Component)__instance).transform.position;
			float num = float.MaxValue;
			IntPtr intPtr = IntPtr.Zero;
			foreach (KeyValuePair<IntPtr, string> entry in officerRoles)
			{
				if (!(entry.Value == "Chaser"))
				{
					continue;
				}
				PoliceOfficer val = ((IEnumerable<PoliceOfficer>)Object.FindObjectsOfType<PoliceOfficer>())?.FirstOrDefault((Func<PoliceOfficer, bool>)((PoliceOfficer p) => ((p != null) ? new IntPtr?(((Il2CppObjectBase)p).Pointer) : null) == entry.Key));
				if ((Object)(object)val != (Object)null)
				{
					float num2 = Vector3.Distance(position, ((Component)val).transform.position);
					if (num2 < num)
					{
						num = num2;
						intPtr = entry.Key;
					}
				}
			}
			if (num < 20f && intPtr != IntPtr.Zero)
			{
				officerRoles[pointer] = "Interceptor";
			}
			else
			{
				officerRoles[pointer] = "Chaser";
			}
		}
		if (!RadioedOfficers)
		{
			RadioedOfficers = true;
			MelonCoroutines.Start(RadioNearbyPolice(__instance));
		}
	}

	private static void OnPursuitEnd_Postfix(PursuitBehaviour __instance)
	{
		object obj;
		if (__instance == null)
		{
			obj = null;
		}
		else
		{
			NPC npc = ((Behaviour)__instance).Npc;
			if (npc == null)
			{
				obj = null;
			}
			else
			{
				NPCMovement movement = npc.Movement;
				obj = ((movement != null) ? movement.SpeedController : null);
			}
		}
		if ((Object)obj != (Object)null)
		{
			((Behaviour)__instance).Npc.Movement.SpeedController.RemoveSpeedControl("hardcore_chase");
			boostedNpcs.Remove(((Il2CppObjectBase)((Behaviour)__instance).Npc).Pointer);
		}
		IntPtr pointer = ((Il2CppObjectBase)((Behaviour)__instance).Npc).Pointer;
		lastAssignedIntercept.Remove(pointer);
		flankTimers.Remove(pointer);
		officerRoles.Remove(pointer);
	}

	private static void OnPursuitTimeout_Postfix(PlayerCrimeData __instance, EPursuitLevel level)
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)__instance) || (Object)(object)__instance.Player == (Object)null || (int)level == 0)
		{
			return;
		}
		MelonLogger.Msg("[Hardcore Police] Pursuit ended - performing full reset");
		stuckTimers.Clear();
		lastSpeedMultiplier.Clear();
		lastSpeedUpdateTime.Clear();
		officerRoles.Clear();
		lastAssignedIntercept.Clear();
		flankTimers.Clear();
		RadioedOfficers = false;
		Enumerator<PoliceOfficer> enumerator = PoliceOfficer.Officers.GetEnumerator();
		while (enumerator.MoveNext())
		{
			PoliceOfficer current = enumerator.Current;
			if (!((Object)(object)current == (Object)null) && (Object)(object)current.PursuitBehaviour != (Object)null && (Object)(object)current.PursuitBehaviour.TargetPlayer == (Object)(object)__instance.Player)
			{
				object obj;
				if (current == null)
				{
					obj = null;
				}
				else
				{
					NPCMovement movement = ((NPC)current).Movement;
					obj = ((movement != null) ? movement.SpeedController : null);
				}
				if ((Object)obj != (Object)null)
				{
					((NPC)current).Movement.SpeedController.RemoveSpeedControl("hardcore_chase");
				}
			}
		}
	}

	private static void UpdateArrest_Postfix(PursuitBehaviour __instance, float tick)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: 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_013c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)((__instance != null) ? __instance.TargetPlayer : null) == (Object)null)
		{
			return;
		}
		bool flag = __instance.sync___get_value_isTargetVisible();
		Vector3 centerPoint = __instance.TargetPlayer.Avatar.CenterPoint;
		float num = Vector3.Distance(((Component)__instance).transform.position, centerPoint);
		if (config.ArrestAdjustments && flag && num <= config.ArrestCooldownCircleDistance)
		{
			__instance.arrestingEnabled = true;
			__instance.timeWithinArrestRange += tick;
			float num2 = __instance.timeWithinArrestRange / config.ArrestProgressSpeed;
			if (((NetworkBehaviour)__instance.TargetPlayer).IsOwner && num2 > __instance.TargetPlayer.CrimeData.CurrentArrestProgress)
			{
				__instance.TargetPlayer.CrimeData.SetArrestProgress(num2);
			}
		}
		ApplySpeedBoostOnce(__instance);
		ApplyDistanceBasedSpeedBoost(__instance);
		Vector3 val = (flag ? GetFlankDestination(__instance) : __instance.TargetPlayer.CrimeData.LastKnownPosition);
		if (config.Flanking && (!((Behaviour)__instance).Npc.Movement.IsMoving || Vector3.Distance(((Behaviour)__instance).Npc.Movement.CurrentDestination, val) > 2.5f) && ((Behaviour)__instance).Npc.Movement.CanGetTo(val, 1.5f))
		{
			((Behaviour)__instance).Npc.Movement.SetDestination(val);
		}
	}

	private static IEnumerator RadioNearbyPolice(PursuitBehaviour originOfficer)
	{
		if (!config.RadioNearby || (Object)(object)originOfficer == (Object)null)
		{
			yield break;
		}
		yield return (object)new WaitForSeconds(4f);
		if ((Object)(object)originOfficer == (Object)null || (Object)(object)originOfficer.TargetPlayer == (Object)null)
		{
			yield break;
		}
		Player player = originOfficer.TargetPlayer;
		Vector3 centerPoint = player.Avatar.CenterPoint;
		int num = 10;
		List<(PoliceOfficer officer, float distanceSqr)> candidateOfficers = new List<(PoliceOfficer, float)>(num);
		float num2 = config.RadioDistance * config.RadioDistance;
		Enumerator<PoliceOfficer> enumerator = PoliceOfficer.Officers.GetEnumerator();
		while (enumerator.MoveNext())
		{
			PoliceOfficer current = enumerator.Current;
			if ((Object)(object)current == (Object)null || (Object)(object)current == (Object)(object)originOfficer || (Object)(object)current.PursuitBehaviour == (Object)null || ((Behaviour)current.PursuitBehaviour).Active)
			{
				continue;
			}
			Vector3 val = ((Component)current).transform.position - centerPoint;
			float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
			if (sqrMagnitude <= num2)
			{
				candidateOfficers.Add((current, sqrMagnitude));
				if ((float)candidateOfficers.Count >= (float)num * 1.5f)
				{
					break;
				}
			}
		}
		candidateOfficers.Sort(((PoliceOfficer officer, float distanceSqr) a, (PoliceOfficer officer, float distanceSqr) b) => a.distanceSqr.CompareTo(b.distanceSqr));
		int officersToQueue = Mathf.Min(candidateOfficers.Count, num);
		if (officersToQueue <= 0)
		{
			yield break;
		}
		MelonLogger.Msg($"[Hardcore Police] Queueing {officersToQueue} officers for backup over {officersToQueue * 3} seconds...");
		for (int i = 0; i < officersToQueue; i++)
		{
			if ((Object)(object)originOfficer == (Object)null || (Object)(object)originOfficer.TargetPlayer == (Object)null || !((Behaviour)originOfficer).Active || (int)player.CrimeData.CurrentPursuitLevel == 0)
			{
				MelonLogger.Msg("[Hardcore Police] Pursuit ended, stopping officer activation");
				break;
			}
			candidateOfficers[i].officer.BeginFootPursuit_Networked(((NetworkBehaviour)player).NetworkObject, false);
			MelonLogger.Msg($"[Hardcore Police] Officer {i + 1}/{officersToQueue} activated");
			float num3 = Random.Range(2f, 4f);
			yield return (object)new WaitForSeconds(num3);
		}
	}

	private static Vector3 GetFlankDestination(PursuitBehaviour pursuit)
	{
		//IL_0025: 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)
		//IL_009e: 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_0064: 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_00b7: 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_00e5: 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_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: 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_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_0195: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//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_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: 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_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		NPC npc = ((Behaviour)pursuit).Npc;
		Player targetPlayer = pursuit.TargetPlayer;
		IntPtr pointer = ((Il2CppObjectBase)npc).Pointer;
		if (!config.Flanking)
		{
			return targetPlayer.CrimeData.LastKnownPosition;
		}
		float time = Time.time;
		if (flankTimers.TryGetValue(pointer, out var value) && time - value < config.FlankUpdateCooldown)
		{
			if (!lastAssignedIntercept.TryGetValue(pointer, out var value2))
			{
				return targetPlayer.CrimeData.LastKnownPosition;
			}
			return value2;
		}
		flankTimers[pointer] = time;
		string value3;
		string text = (officerRoles.TryGetValue(pointer, out value3) ? value3 : "Chaser");
		Vector3 centerPoint = targetPlayer.Avatar.CenterPoint;
		Rigidbody component = ((Component)targetPlayer.Avatar).GetComponent<Rigidbody>();
		Vector3 val = (((Object)(object)component != (Object)null) ? component.velocity : Vector3.zero);
		float magnitude = ((Vector3)(ref val)).magnitude;
		if (magnitude < 0.1f)
		{
			return targetPlayer.CrimeData.LastKnownPosition;
		}
		Vector3 val2 = val / magnitude;
		float num = ((text == "Interceptor") ? 8f : 2f);
		Vector3 val3 = centerPoint + val2 * magnitude * num;
		if (text == "Interceptor")
		{
			Vector3 val4 = Vector3.Cross(Vector3.up, val2);
			int hashCode = pointer.GetHashCode();
			float num2 = 8f + (float)(hashCode % 8);
			bool flag = (hashCode & 1) == 0;
			val3 += val4 * (flag ? (0f - num2) : num2);
		}
		else
		{
			int hashCode2 = pointer.GetHashCode();
			float num3 = 2f + (float)(hashCode2 % 3);
			val3 -= val2 * num3;
		}
		bool flag2 = true;
		if (lastAssignedIntercept.TryGetValue(pointer, out var value4))
		{
			flag2 = Vector3.SqrMagnitude(val3 - value4) > 9f;
		}
		Vector3 value5;
		if (flag2)
		{
			NavMeshHit val5 = default(NavMeshHit);
			if (NavMesh.SamplePosition(val3, ref val5, 10f, -1))
			{
				lastAssignedIntercept[pointer] = ((NavMeshHit)(ref val5)).position;
				return ((NavMeshHit)(ref val5)).position;
			}
		}
		else if (lastAssignedIntercept.TryGetValue(pointer, out value5))
		{
			return value5;
		}
		return targetPlayer.CrimeData.LastKnownPosition;
	}

	private static void ApplyDistanceBasedSpeedBoost(PursuitBehaviour __instance)
	{
		//IL_0081: 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)
		//IL_0096: 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_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Expected O, but got Unknown
		if (!config.DistanceSpeedBoost)
		{
			return;
		}
		object obj;
		if (__instance == null)
		{
			obj = null;
		}
		else
		{
			NPC npc = ((Behaviour)__instance).Npc;
			if (npc == null)
			{
				obj = null;
			}
			else
			{
				NPCMovement movement = npc.Movement;
				obj = ((movement != null) ? movement.SpeedController : null);
			}
		}
		if ((Object)obj == (Object)null || (Object)(object)__instance.TargetPlayer == (Object)null)
		{
			return;
		}
		IntPtr pointer = ((Il2CppObjectBase)((Behaviour)__instance).Npc).Pointer;
		float time = Time.time;
		if (lastSpeedUpdateTime.ContainsKey(pointer) && time - lastSpeedUpdateTime[pointer] < 0.25f)
		{
			return;
		}
		Vector3 position = ((Component)__instance).transform.position;
		Vector3 centerPoint = __instance.TargetPlayer.Avatar.CenterPoint;
		float num = Mathf.Clamp(Vector3.Distance(position, centerPoint), 0f, config.DistanceMax);
		float num2 = Mathf.Lerp(config.DistanceBoostBase, config.DistanceBoostMax, num / 100f);
		lastSpeedMultiplier.TryGetValue(pointer, out var value);
		if (Mathf.Abs(num2 - value) > 0.05f)
		{
			NPCMovement movement2 = ((Behaviour)__instance).Npc.Movement;
			NPCSpeedController speedController = movement2.SpeedController;
			speedController.SpeedMultiplier = num2;
			movement2.MovementSpeedScale = num2 * 0.92f;
			movement2.MoveSpeedMultiplier = num2 * 0.92f;
			if (speedController.DoesSpeedControlExist("hardcore_chase"))
			{
				speedController.RemoveSpeedControl("hardcore_chase");
			}
			speedController.AddSpeedControl(new SpeedControl("hardcore_chase", 50, num2));
			lastSpeedMultiplier[pointer] = num2;
			lastSpeedUpdateTime[pointer] = time;
		}
	}

	private static void ApplySpeedBoostOnce(PursuitBehaviour __instance)
	{
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Expected O, but got Unknown
		if (!config.SpeedBoost)
		{
			return;
		}
		object obj;
		if (__instance == null)
		{
			obj = null;
		}
		else
		{
			NPC npc = ((Behaviour)__instance).Npc;
			if (npc == null)
			{
				obj = null;
			}
			else
			{
				NPCMovement movement = npc.Movement;
				obj = ((movement != null) ? movement.SpeedController : null);
			}
		}
		if (!((Object)obj == (Object)null))
		{
			IntPtr pointer = ((Il2CppObjectBase)((Behaviour)__instance).Npc).Pointer;
			if (!boostedNpcs.Contains(pointer))
			{
				boostedNpcs.Add(pointer);
				NPCMovement movement2 = ((Behaviour)__instance).Npc.Movement;
				NPCSpeedController speedController = movement2.SpeedController;
				speedController.SpeedMultiplier = config.SpeedBoostMultiplier;
				movement2.MovementSpeedScale = config.MovementSpeedScale;
				movement2.MoveSpeedMultiplier = config.MoveSpeedMultiplier;
				speedController.AddSpeedControl(new SpeedControl("hardcore_chase", 50, config.SpeedBoostMultiplier));
				movement2.SetStance((EStance)1);
			}
		}
	}
}