Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of HardcoreAI v1.1.0
HardcorePolice.dll
Decompiled 10 months agousing 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); } } } }