Decompiled source of NoPolice v1.1.0

NoPolice.dll

Decompiled 6 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using NoPolice;
using NoPolice.Patches;
using NoPolice.Utils;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "NoPolice", "1.1.0", "HazDS", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("NoPolice")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2a1bee382a54f761b1dfb1fee140eeb7e504e26c")]
[assembly: AssemblyProduct("NoPolice")]
[assembly: AssemblyTitle("NoPolice")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NoPolice
{
	public static class Config
	{
		private static MelonPreferences_Category _category;

		private static MelonPreferences_Entry<bool> _disablePatrols;

		private static MelonPreferences_Entry<bool> _disableCheckpoints;

		private static MelonPreferences_Entry<bool> _disableCurfew;

		private static MelonPreferences_Entry<bool> _disableDispatch;

		private static MelonPreferences_Entry<bool> _disablePursuits;

		private static MelonPreferences_Entry<bool> _disableBodySearches;

		private static MelonPreferences_Entry<bool> _debugLogging;

		public static bool DisablePatrols => _disablePatrols?.Value ?? true;

		public static bool DisableCheckpoints => _disableCheckpoints?.Value ?? true;

		public static bool DisableCurfew => _disableCurfew?.Value ?? true;

		public static bool DisableDispatch => _disableDispatch?.Value ?? true;

		public static bool DisablePursuits => _disablePursuits?.Value ?? true;

		public static bool DisableBodySearches => _disableBodySearches?.Value ?? true;

		public static bool DebugLogging => _debugLogging?.Value ?? false;

		public static void Initialize()
		{
			_category = MelonPreferences.CreateCategory("NoPolice", "NoPolice Settings");
			_disablePatrols = _category.CreateEntry<bool>("DisablePatrols", true, "Disable Patrols", "Prevents foot patrols, vehicle patrols, and sentry posts from activating.", false, false, (ValueValidator)null, (string)null);
			_disableCheckpoints = _category.CreateEntry<bool>("DisableCheckpoints", true, "Disable Checkpoints", "Prevents road checkpoints from being set up.", false, false, (ValueValidator)null, (string)null);
			_disableCurfew = _category.CreateEntry<bool>("DisableCurfew", true, "Disable Curfew", "Prevents curfew from being enforced.", false, false, (ValueValidator)null, (string)null);
			_disableDispatch = _category.CreateEntry<bool>("DisableDispatch", true, "Disable Dispatch", "Prevents police from being dispatched when crimes are reported.", false, false, (ValueValidator)null, (string)null);
			_disablePursuits = _category.CreateEntry<bool>("DisablePursuits", true, "Disable Pursuits", "Prevents police from initiating foot and vehicle pursuits.", false, false, (ValueValidator)null, (string)null);
			_disableBodySearches = _category.CreateEntry<bool>("DisableBodySearches", true, "Disable Body Searches", "Prevents officers from investigating and body searching players.", false, false, (ValueValidator)null, (string)null);
			_debugLogging = _category.CreateEntry<bool>("DebugLogging", false, "Debug Logging", "Logs config value reads to help diagnose issues.", false, false, (ValueValidator)null, (string)null);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_disablePatrols.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg($"[Config] DisablePatrols: {oldVal} -> {newVal}");
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_disableCheckpoints.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg($"[Config] DisableCheckpoints: {oldVal} -> {newVal}");
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_disableCurfew.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg($"[Config] DisableCurfew: {oldVal} -> {newVal}");
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_disableDispatch.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg($"[Config] DisableDispatch: {oldVal} -> {newVal}");
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_disablePursuits.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg($"[Config] DisablePursuits: {oldVal} -> {newVal}");
			}, 0, false);
			((MelonEventBase<LemonAction<bool, bool>>)(object)_disableBodySearches.OnEntryValueChanged).Subscribe((LemonAction<bool, bool>)delegate(bool oldVal, bool newVal)
			{
				MelonLogger.Msg($"[Config] DisableBodySearches: {oldVal} -> {newVal}");
			}, 0, false);
			LogCurrentConfig();
		}

		public static void LogCurrentConfig()
		{
			MelonLogger.Msg($"[Config] Patrols={DisablePatrols} Checkpoints={DisableCheckpoints} " + $"Curfew={DisableCurfew} Dispatch={DisableDispatch} " + $"Pursuits={DisablePursuits} BodySearches={DisableBodySearches}");
		}
	}
	public class Core : MelonMod
	{
		private Harmony _harmony;

		private int _patchedCount;

		public override void OnInitializeMelon()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Config.Initialize();
			_harmony = new Harmony("com.nopolice.patches");
			_patchedCount = 0;
			PatchPatrols();
			PatchCheckpoints();
			PatchCurfew();
			PatchDispatch();
			PatchPursuits();
			PatchBodySearches();
			MelonLogger.Msg(string.Format("{0} v{1} loaded! ({2} patches applied)", "NoPolice", "1.1.0", _patchedCount));
		}

		private void PatchPatrols()
		{
			PatchTypeMethod("ScheduleOne.Law.PatrolInstance", "Evaluate", "PatrolEvaluate_Prefix");
			PatchTypeMethod("ScheduleOne.Law.VehiclePatrolInstance", "Evaluate", "VehiclePatrolEvaluate_Prefix");
			PatchTypeMethod("ScheduleOne.Law.SentryInstance", "Evaluate", "SentryEvaluate_Prefix");
		}

		private void PatchCheckpoints()
		{
			PatchTypeMethod("ScheduleOne.Law.CheckpointInstance", "Evaluate", "CheckpointEvaluate_Prefix");
		}

		private void PatchCurfew()
		{
			PatchTypeMethod("ScheduleOne.Law.CurfewInstance", "Evaluate", "CurfewEvaluate_Prefix");
		}

		private void PatchDispatch()
		{
			PatchTypeMethod("ScheduleOne.Law.LawManager", "PoliceCalled", "PoliceCalled_Prefix");
			PatchTypeMethod("ScheduleOne.Map.PoliceStation", "Dispatch", "Dispatch_Prefix");
		}

		private void PatchPursuits()
		{
			PatchTypeMethod("ScheduleOne.Police.PoliceOfficer", "BeginFootPursuit_Networked", "BeginFootPursuit_Prefix");
			PatchTypeMethod("ScheduleOne.Police.PoliceOfficer", "BeginVehiclePursuit_Networked", "BeginVehiclePursuit_Prefix");
		}

		private void PatchBodySearches()
		{
			PatchTypeMethod("ScheduleOne.Police.PoliceOfficer", "BeginBodySearch_Networked", "BeginBodySearch_Prefix");
			PatchTypeMethod("ScheduleOne.Police.PoliceOfficer", "CheckNewInvestigation", "CheckNewInvestigation_Prefix");
		}

		private void PatchTypeMethod(string typeName, string methodName, string prefixMethodName)
		{
			Type type = CrossCompat.FindType(typeName);
			if (type == null)
			{
				MelonLogger.Error("Type not found: " + typeName);
			}
			else
			{
				PatchMethod(type, methodName, prefixMethodName);
			}
		}

		private void PatchMethod(Type targetType, string methodName, string prefixMethodName)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			try
			{
				MethodInfo method = targetType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method == null)
				{
					MelonLogger.Warning("Method not found: " + targetType.Name + "." + methodName);
					return;
				}
				MethodInfo method2 = typeof(PolicePatches).GetMethod(prefixMethodName, BindingFlags.Static | BindingFlags.Public);
				if (method2 == null)
				{
					MelonLogger.Error("Prefix method not found: " + prefixMethodName);
					return;
				}
				_harmony.Patch((MethodBase)method, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_patchedCount++;
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Failed to patch " + targetType.Name + "." + methodName + ": " + ex.Message);
				MelonLogger.Error("Stack trace: " + ex.StackTrace);
			}
		}
	}
}
namespace NoPolice.Utils
{
	public static class Constants
	{
		public static class Game
		{
			public const string GAME_STUDIO = "TVGS";

			public const string GAME_NAME = "Schedule I";
		}

		public const string MOD_NAME = "NoPolice";

		public const string MOD_VERSION = "1.1.0";

		public const string MOD_AUTHOR = "HazDS";

		public const string HARMONY_ID = "com.nopolice.patches";
	}
	public static class CrossCompat
	{
		public static Type FindType(string fullName)
		{
			string name = (fullName.StartsWith("ScheduleOne") ? ("Il2Cpp" + fullName) : fullName);
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = assembly.GetType(fullName) ?? assembly.GetType(name);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
}
namespace NoPolice.Patches
{
	public static class PolicePatches
	{
		public static bool PatrolEvaluate_Prefix()
		{
			bool disablePatrols = Config.DisablePatrols;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] PatrolEvaluate blocked={disablePatrols}");
			}
			return !disablePatrols;
		}

		public static bool VehiclePatrolEvaluate_Prefix()
		{
			bool disablePatrols = Config.DisablePatrols;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] VehiclePatrolEvaluate blocked={disablePatrols}");
			}
			return !disablePatrols;
		}

		public static bool SentryEvaluate_Prefix()
		{
			bool disablePatrols = Config.DisablePatrols;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] SentryEvaluate blocked={disablePatrols}");
			}
			return !disablePatrols;
		}

		public static bool CheckpointEvaluate_Prefix()
		{
			bool disableCheckpoints = Config.DisableCheckpoints;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] CheckpointEvaluate blocked={disableCheckpoints}");
			}
			return !disableCheckpoints;
		}

		public static bool CurfewEvaluate_Prefix()
		{
			bool disableCurfew = Config.DisableCurfew;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] CurfewEvaluate blocked={disableCurfew}");
			}
			return !disableCurfew;
		}

		public static bool PoliceCalled_Prefix()
		{
			bool disableDispatch = Config.DisableDispatch;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] PoliceCalled blocked={disableDispatch}");
			}
			return !disableDispatch;
		}

		public static bool Dispatch_Prefix()
		{
			bool disableDispatch = Config.DisableDispatch;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] Dispatch blocked={disableDispatch}");
			}
			return !disableDispatch;
		}

		public static bool BeginFootPursuit_Prefix()
		{
			bool disablePursuits = Config.DisablePursuits;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] BeginFootPursuit blocked={disablePursuits}");
			}
			return !disablePursuits;
		}

		public static bool BeginVehiclePursuit_Prefix()
		{
			bool disablePursuits = Config.DisablePursuits;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] BeginVehiclePursuit blocked={disablePursuits}");
			}
			return !disablePursuits;
		}

		public static bool BeginBodySearch_Prefix()
		{
			bool disableBodySearches = Config.DisableBodySearches;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] BeginBodySearch blocked={disableBodySearches}");
			}
			return !disableBodySearches;
		}

		public static bool CheckNewInvestigation_Prefix()
		{
			bool disableBodySearches = Config.DisableBodySearches;
			if (Config.DebugLogging)
			{
				MelonLogger.Msg($"[Prefix] CheckNewInvestigation blocked={disableBodySearches}");
			}
			return !disableBodySearches;
		}
	}
}