Decompiled source of PickPocket Police v1.0.4

Mods/PickPocketCops.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using HarmonyLib;
using Il2CppFishNet;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Law;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Police;
using Il2CppScheduleOne.UI;
using Il2CppSystem.Collections.Generic;
using LawEnforcementEnhancementMod;
using MelonLoader;
using PickPocketCops;
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::PickPocketCops.PickPocketCops), "PickPocketCops", "1.0.4", "SadPoty", null)]
[assembly: MelonColor]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: AssemblyTitle("PickPocketCops")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PickPocketCops")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("d1556862-e875-420b-a75a-0d5675320f5e")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace PickPocketCops;

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

	public const string Description = "Make cops pickpockable";

	public const string Author = "SadPoty";

	public const string Company = null;

	public const string Version = "1.0.4";

	public const string DownloadLink = null;
}
public class PickPocketCops : MelonMod
{
	private Type policeManagerType = AccessTools.TypeByName("LawEnforcementEnhancementMod.OfficerSpawnSystem");

	private static List<PoliceOfficer> SpawnedOfficer = new List<PoliceOfficer>();

	public static bool IsLEEPatch = false;

	public override void OnSceneWasLoaded(int buildIndex, string sceneName)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Expected O, but got Unknown
		if (sceneName == "Main")
		{
			if (policeManagerType != null)
			{
				MethodInfo methodInfo = AccessTools.Method(policeManagerType, "SpawnOfficer", (Type[])null, (Type[])null);
				MethodInfo method = typeof(PickPocketCops).GetMethod("PostEnablePickPocket", BindingFlags.Static | BindingFlags.NonPublic);
				((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null);
				IsLEEPatch = true;
				MelonLogger.Msg("LawEnforcementEnhancementMod detected !");
			}
			EnablePickpocketOnOfficers();
		}
	}

	public static List<PoliceOfficer> GetAllOfficers()
	{
		Il2CppArrayBase<PoliceOfficer> val = Object.FindObjectsOfType<PoliceOfficer>();
		List<PoliceOfficer> val2 = new List<PoliceOfficer>(val.Length);
		foreach (PoliceOfficer item in val)
		{
			val2.Add(item);
		}
		return val2;
	}

	private static void EnablePickpocketOnOfficers()
	{
		Il2CppArrayBase<PoliceOfficer> val = Object.FindObjectsOfType<PoliceOfficer>();
		List<PoliceOfficer> allOfficers = GetAllOfficers();
		foreach (PoliceOfficer item in val)
		{
			allOfficers.Add(item);
		}
		foreach (PoliceOfficer item2 in val)
		{
			if ((Object)(object)item2 != (Object)null && (Object)(object)((NPC)item2).Inventory != (Object)null)
			{
				((NPC)item2).Inventory.CanBePickpocketed = true;
				((NPC)item2).Inventory.RandomCash = true;
				SetupCustomLootPool(item2);
			}
		}
		DistributeRandomLootToOfficers(allOfficers);
		MelonLogger.Msg("PickPocketCops Loaded !");
	}

	private static void SetupCustomLootPool(PoliceOfficer officer)
	{
		Il2CppArrayBase<ItemDefinition> itemDefs = Resources.FindObjectsOfTypeAll<ItemDefinition>();
		List<StorableItemDefinition> lootList = new List<StorableItemDefinition>();
		StorableItemDefinition val = GetItem("Donut");
		if ((Object)(object)val != (Object)null)
		{
			AddItemMultiple(val, 6);
		}
		StorableItemDefinition val2 = GetItem("M1911");
		if ((Object)(object)val2 != (Object)null)
		{
			AddItemMultiple(val2, 1);
		}
		StorableItemDefinition val3 = GetItem("Revolver");
		if ((Object)(object)val3 != (Object)null)
		{
			AddItemMultiple(val3, 1);
		}
		StorableItemDefinition val4 = GetItem("RevolverCylinder");
		if ((Object)(object)val4 != (Object)null)
		{
			AddItemMultiple(val4, 3);
		}
		StorableItemDefinition val5 = GetItem("M1911_Magazine");
		if ((Object)(object)val5 != (Object)null)
		{
			AddItemMultiple(val5, 3);
		}
		Il2CppReferenceArray<StorableItemDefinition> val6 = new Il2CppReferenceArray<StorableItemDefinition>((long)lootList.Count);
		for (int i = 0; i < lootList.Count; i++)
		{
			((Il2CppArrayBase<StorableItemDefinition>)(object)val6)[i] = lootList[i];
		}
		((NPC)officer).Inventory.RandomItemDefinitions = val6;
		void AddItemMultiple(StorableItemDefinition item, int count)
		{
			for (int j = 0; j < count; j++)
			{
				lootList.Add(item);
			}
		}
		StorableItemDefinition GetItem(string name)
		{
			ItemDefinition val7 = ((IEnumerable<ItemDefinition>)itemDefs).FirstOrDefault((Func<ItemDefinition, bool>)((ItemDefinition d) => ((Object)d).name == name));
			return (val7 != null) ? ((Il2CppObjectBase)val7).TryCast<StorableItemDefinition>() : null;
		}
	}

	public static void DistributeRandomLootToOfficers(List<PoliceOfficer> officers)
	{
		//IL_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Expected O, but got Unknown
		if (officers == null || officers.Count == 0)
		{
			return;
		}
		int num = Mathf.Min(Random.Range(7, officers.Count + 1), officers.Count);
		List<int> list = new List<int>();
		while (list.Count < num)
		{
			int item = Random.Range(0, officers.Count);
			if (!list.Contains(item))
			{
				list.Add(item);
			}
		}
		foreach (int item2 in list)
		{
			PoliceOfficer val = officers[item2];
			Il2CppReferenceArray<StorableItemDefinition> randomItemDefinitions = ((NPC)val).Inventory.RandomItemDefinitions;
			if (randomItemDefinitions == null || ((Il2CppArrayBase<StorableItemDefinition>)(object)randomItemDefinitions).Length == 0)
			{
				continue;
			}
			StorableItemDefinition val2 = ((Il2CppArrayBase<StorableItemDefinition>)(object)randomItemDefinitions)[Random.Range(0, ((Il2CppArrayBase<StorableItemDefinition>)(object)randomItemDefinitions).Length)];
			if (!((Object)(object)val2 == (Object)null))
			{
				int num2 = 1;
				int num3;
				switch (((Object)val2).name)
				{
				case "Revolver":
				case "RevolverCylinder":
					num3 = 6;
					break;
				case "M1911":
				case "M1911_Magazine":
					num3 = 7;
					break;
				default:
					num3 = 1;
					break;
				}
				IntegerItemInstance val3 = new IntegerItemInstance((ItemDefinition)(object)val2, num2, num3);
				((NPC)val).Inventory.InsertItem((ItemInstance)(object)val3, true);
			}
		}
	}

	private static void PostEnablePickPocket(Vector3 position, District district, bool isForDistrictPopulation)
	{
		if (InstanceFinder.NetworkManager.IsClientOnly)
		{
			List<PoliceOfficer> officers = PoliceOfficer.Officers;
			Enumerator<PoliceOfficer> enumerator = officers.GetEnumerator();
			while (enumerator.MoveNext())
			{
				PoliceOfficer current = enumerator.Current;
				((NPC)current).Inventory.CanBePickpocketed = true;
			}
			return;
		}
		Type type = AccessTools.TypeByName("LawEnforcementEnhancementMod.Core");
		PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
		object value = property.GetValue(null);
		PropertyInfo property2 = type.GetProperty("OfficerSpawnSystem", BindingFlags.Instance | BindingFlags.Public);
		object value2 = property2.GetValue(value);
		Type type2 = value2.GetType();
		FieldInfo field = type2.GetField("_activeOfficers", BindingFlags.Instance | BindingFlags.NonPublic);
		List<PoliceOfficer> list = field.GetValue(value2) as List<PoliceOfficer>;
		if (type == null)
		{
			MelonLogger.Error("Core type not found!");
			return;
		}
		if (property == null)
		{
			MelonLogger.Error("Core.Instance property not found!");
			return;
		}
		if (value == null)
		{
			MelonLogger.Error("Core.Instance is null!");
			return;
		}
		if (property2 == null)
		{
			MelonLogger.Error("OfficerSpawnSystem property not found!");
			return;
		}
		if (value2 == null)
		{
			MelonLogger.Error("OfficerSpawnSystem instance is null!");
			return;
		}
		if (field == null)
		{
			MelonLogger.Error("_activeOfficers field not found!");
			return;
		}
		if (list == null)
		{
			MelonLogger.Error("_activeOfficers list is null!");
			return;
		}
		PoliceOfficer val = list.Last();
		SpawnedOfficer.Add(val);
		((NPC)val).Inventory.CanBePickpocketed = true;
		((NPC)val).Inventory.RandomCash = true;
		SetupCustomLootPool(val);
		DistributeRandomLootToOfficer(val);
	}

	public static List<PoliceOfficer> GetSpawnedOfficers()
	{
		return SpawnedOfficer;
	}

	public static bool GetLEEPatch()
	{
		return IsLEEPatch;
	}

	public static void DistributeRandomLootToOfficer(PoliceOfficer officer)
	{
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Expected O, but got Unknown
		Il2CppReferenceArray<StorableItemDefinition> randomItemDefinitions = ((NPC)officer).Inventory.RandomItemDefinitions;
		StorableItemDefinition val = ((Il2CppArrayBase<StorableItemDefinition>)(object)randomItemDefinitions)[Random.Range(0, ((Il2CppArrayBase<StorableItemDefinition>)(object)randomItemDefinitions).Length)];
		int num = 1;
		int num2;
		switch (((Object)val).name)
		{
		case "Revolver":
		case "RevolverCylinder":
			num2 = 6;
			break;
		case "M1911":
		case "M1911_Magazine":
			num2 = 7;
			break;
		default:
			num2 = 1;
			break;
		}
		IntegerItemInstance val2 = new IntegerItemInstance((ItemDefinition)(object)val, num, num2);
		((NPC)officer).Inventory.InsertItem((ItemInstance)(object)val2, true);
	}
}
[HarmonyPatch(typeof(PickpocketScreen), "Update")]
public static class PickpocketScreenUpdatePatch
{
	private static bool PickFailed = false;

	private static Vector3 oldDestination = default(Vector3);

	private static void Postfix(PickpocketScreen __instance)
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: 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_00bc: 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_0105: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Expected O, but got Unknown
		if ((Object)(object)__instance.npc == (Object)null || !((Object)__instance.npc).name.StartsWith("Officer"))
		{
			return;
		}
		if (__instance.IsOpen && !PickFailed)
		{
			NPC npc = __instance.npc;
			npc.Movement.MoveSpeedMultiplier = 0f;
			oldDestination = npc.Movement.CurrentDestination;
			PickFailed = true;
		}
		else if (!__instance.IsOpen && PickFailed)
		{
			NPC npc2 = __instance.npc;
			npc2.Movement.MoveSpeedMultiplier = 1f;
			if (oldDestination != Vector3.zero)
			{
				npc2.Movement.SetDestination(oldDestination);
			}
			else
			{
				npc2.Movement.SetDestination(((Component)npc2).transform.position + new Vector3(1f, 0f, 1f));
			}
			PickFailed = false;
		}
		if (__instance.isFail && !__instance.npc.Health.IsKnockedOut && !__instance.npc.Health.IsDead)
		{
			Player local = Player.Local;
			if ((Object)(object)local != (Object)null && !InstanceFinder.NetworkManager.IsClientOnly)
			{
				PoliceOfficer nearestOfficer = local.CrimeData.NearestOfficer;
				local.CrimeData.SetPursuitLevel((EPursuitLevel)3);
				local.CrimeData.AddCrime((Crime)new Theft(), 2);
				nearestOfficer.BeginFootPursuit_Networked(((NetworkBehaviour)local).NetworkObject, true);
				((Behaviour)nearestOfficer.PursuitBehaviour).SendEnable();
			}
			__instance.isFail = false;
			((Singleton<PickpocketScreen>)(object)__instance).OnDestroy();
			((Singleton<PickpocketScreen>)(object)__instance).Awake();
		}
	}
}
[HarmonyPatch(typeof(TimeManager), "MarkHostSleepDone")]
public static class RestockOfficerPatch
{
	private static void Postfix(TimeManager __instance)
	{
		List<PoliceOfficer> allOfficers = PickPocketCops.GetAllOfficers();
		PickPocketCops.DistributeRandomLootToOfficers(allOfficers);
		if (!PickPocketCops.GetLEEPatch())
		{
			return;
		}
		List<PoliceOfficer> spawnedOfficers = PickPocketCops.GetSpawnedOfficers();
		foreach (PoliceOfficer item in spawnedOfficers)
		{
			PickPocketCops.DistributeRandomLootToOfficer(item);
		}
	}
}