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 a month 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); } } } }