Decompiled source of RacingManhunt v1.1.2

BepInEx/plugins/PeakManhuntRacing.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace PeakManhuntRacing;

[BepInPlugin("com.peak.manhunt.racing", "PEAK Manhunt/Racing Mod", "1.1.2")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "com.peak.manhunt.racing";

	public const string PluginName = "PEAK Manhunt/Racing Mod";

	public const string PluginVersion = "1.1.2";

	internal static ManualLogSource Log;

	internal static bool SuppressNextFogOriginReset;

	private void Awake()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		try
		{
			new Harmony("com.peak.manhunt.racing").PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"Rebuilt PEAK Manhunt/Racing patches applied.");
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Failed to apply rebuilt patches: " + ex));
		}
	}
}
[HarmonyPatch]
internal static class CampfireEveryoneInRangeFloatPatch
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method(typeof(Campfire), "EveryoneInRange", new Type[1] { typeof(float) }, (Type[])null);
	}

	[HarmonyPrefix]
	private static bool Prefix(ref bool __result)
	{
		__result = true;
		return false;
	}
}
[HarmonyPatch]
internal static class CampfireEveryoneInRangeMessagePatch
{
	private static MethodBase TargetMethod()
	{
		return AccessTools.Method(typeof(Campfire), "EveryoneInRange", new Type[2]
		{
			typeof(string).MakeByRefType(),
			typeof(float)
		}, (Type[])null);
	}

	[HarmonyPrefix]
	private static bool Prefix(Campfire __instance, ref string printout, ref bool __result)
	{
		try
		{
			printout = BuildMissingPlayersText(__instance);
			__result = true;
			return false;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Error in CampfireEveryoneInRangePatch: " + ex));
			return true;
		}
	}

	internal static string BuildMissingPlayersText(Campfire campfire)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		string text = string.Empty;
		Vector3 position = ((Component)campfire).transform.position;
		foreach (Character allPlayerCharacter in PlayerHandler.GetAllPlayerCharacters())
		{
			if (!((Object)(object)allPlayerCharacter == (Object)null) && !((Object)(object)allPlayerCharacter.data == (Object)null) && !allPlayerCharacter.data.dead)
			{
				float num = Vector3.Distance(position, allPlayerCharacter.Center);
				if (!(num <= 15f))
				{
					Player val = (((Object)(object)((MonoBehaviourPun)allPlayerCharacter).photonView != (Object)null) ? ((MonoBehaviourPun)allPlayerCharacter).photonView.Owner : null);
					string text2 = ((val != null) ? val.NickName : "Unknown");
					int num2 = Mathf.RoundToInt(num * CharacterStats.unitsToMeters);
					object obj = text;
					text = string.Concat(obj, "\n", text2, " ", num2, "m");
				}
			}
		}
		return string.IsNullOrEmpty(text) ? string.Empty : ("other players location:" + text);
	}
}
[HarmonyPatch(typeof(Campfire), "GetInteractionText")]
internal static class CampfireGetInteractionTextPatch
{
	[HarmonyPrefix]
	private static bool Prefix(Campfire __instance, ref string __result)
	{
		try
		{
			if (!__instance.Lit)
			{
				string text = CampfireEveryoneInRangeMessagePatch.BuildMissingPlayersText(__instance);
				__result = (string.IsNullOrEmpty(text) ? LocalizedText.GetText("LIGHT", true) : (LocalizedText.GetText("LIGHT", true) + "\n" + text));
				return false;
			}
			__result = LocalizedText.GetText("COOK", true);
			return false;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Error in CampfireGetInteractionTextPatch: " + ex));
			return true;
		}
	}
}
[HarmonyPatch(typeof(Campfire), "Interact_CastFinished")]
internal static class CampfireInteractCastFinishedPatch
{
	private static readonly FieldInfo CurrentCookingItemField = AccessTools.Field(typeof(Campfire), "currentlyCookingItem");

	private static readonly FieldInfo ViewField = AccessTools.Field(typeof(Campfire), "view");

	private static readonly FieldInfo AdvanceToSegmentField = AccessTools.Field(typeof(Campfire), "advanceToSegment");

	[HarmonyPrefix]
	private static bool Prefix(Campfire __instance)
	{
		try
		{
			if (__instance.Lit)
			{
				Item val = (Item)((CurrentCookingItemField != null) ? /*isinst with value type is only supported in some contexts*/: null);
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).GetComponent<ItemCooking>().FinishCooking();
				}
				return false;
			}
			PhotonView val2 = (PhotonView)((ViewField != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val2 == (Object)null)
			{
				Plugin.Log.LogWarning((object)"Campfire view missing, falling back to original interaction.");
				return true;
			}
			Plugin.SuppressNextFogOriginReset = true;
			Plugin.Log.LogInfo((object)"Lighting campfire with normal segment advance path.");
			Plugin.Log.LogInfo((object)("Advance segment: " + ((AdvanceToSegmentField != null) ? AdvanceToSegmentField.GetValue(__instance) : "null")));
			val2.RPC("Light_Rpc", (RpcTarget)0, new object[2] { true, 0f });
			return false;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Error in CampfireInteractCastFinishedPatch: " + ex));
			return true;
		}
	}
}
[HarmonyPatch(typeof(OrbFogHandler), "SetFogOrigin")]
internal static class OrbFogHandlerSetFogOriginPatch
{
	[HarmonyPrefix]
	private static bool Prefix(int id)
	{
		if (!Plugin.SuppressNextFogOriginReset)
		{
			return true;
		}
		Plugin.SuppressNextFogOriginReset = false;
		Plugin.Log.LogInfo((object)("Skipping fog-origin reset after campfire reveal. Requested id: " + id));
		return false;
	}
}
[HarmonyPatch]
internal static class MapHandlerTransitionPatch
{
	private static readonly FieldInfo MapHandlerSegmentsField = AccessTools.Field(typeof(MapHandler), "segments");

	private static readonly FieldInfo MapHandlerCurrentSegmentField = AccessTools.Field(typeof(MapHandler), "currentSegment");

	private static readonly FieldInfo MapSegmentParentField = AccessTools.Field(typeof(MapSegment), "_segmentParent");

	private static readonly FieldInfo MapSegmentCampfireField = AccessTools.Field(typeof(MapSegment), "_segmentCampfire");

	private static readonly FieldInfo MapSegmentWallNextField = AccessTools.Field(typeof(MapSegment), "wallNext");

	private static readonly FieldInfo MapSegmentWallPreviousField = AccessTools.Field(typeof(MapSegment), "wallPrevious");

	private static MethodBase TargetMethod()
	{
		Type[] nestedTypes = typeof(MapHandler).GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
		foreach (Type type in nestedTypes)
		{
			if (type.Name.IndexOf("DisplayClass", StringComparison.Ordinal) < 0)
			{
				continue;
			}
			Type[] nestedTypes2 = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
			foreach (Type type2 in nestedTypes2)
			{
				if (type2.Name.IndexOf("ShowNextSegmentCoroutine", StringComparison.Ordinal) >= 0)
				{
					return AccessTools.Method(type2, "MoveNext", (Type[])null, (Type[])null);
				}
			}
		}
		return null;
	}

	[HarmonyTranspiler]
	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		List<CodeInstruction> list = new List<CodeInstruction>(instructions);
		MethodInfo methodInfo = AccessTools.Method(typeof(GameObject), "SetActive", new Type[1] { typeof(bool) }, (Type[])null);
		MethodInfo methodInfo2 = AccessTools.Method(typeof(MapSegment), "get_segmentCampfire", (Type[])null, (Type[])null);
		bool flag = false;
		bool flag2 = false;
		for (int i = 0; i < list.Count - 1; i++)
		{
			MethodInfo methodInfo3 = list[i + 1].operand as MethodInfo;
			if (list[i + 1].opcode.Equals(OpCodes.Callvirt) && !(methodInfo3 != methodInfo) && !flag && list[i].opcode.Equals(OpCodes.Ldc_I4_0))
			{
				list[i].opcode = OpCodes.Ldc_I4_1;
				flag = true;
				break;
			}
		}
		for (int i = 0; i < list.Count - 1; i++)
		{
			MethodInfo methodInfo3 = list[i + 1].operand as MethodInfo;
			if (!list[i + 1].opcode.Equals(OpCodes.Callvirt) || methodInfo3 != methodInfo || !list[i].opcode.Equals(OpCodes.Ldc_I4_0))
			{
				continue;
			}
			bool flag3 = false;
			int num = i - 1;
			while (num >= 0 && num >= i - 12)
			{
				MethodInfo methodInfo4 = list[num].operand as MethodInfo;
				if ((list[num].opcode.Equals(OpCodes.Callvirt) || list[num].opcode.Equals(OpCodes.Call)) && methodInfo4 == methodInfo2)
				{
					flag3 = true;
					break;
				}
				num--;
			}
			if (flag3)
			{
				list[i].opcode = OpCodes.Ldc_I4_1;
				flag2 = true;
			}
		}
		if (!flag)
		{
			Plugin.Log.LogWarning((object)"Could not find previous-segment deactivation call in transition coroutine.");
		}
		if (!flag2)
		{
			Plugin.Log.LogWarning((object)"Could not find previous campfire-area deactivation call in transition coroutine.");
		}
		return list;
	}

	[HarmonyPostfix]
	private static void Postfix(object __instance, bool __result)
	{
		try
		{
			if (__result)
			{
				return;
			}
			MapHandler mapHandlerFromStateMachine = GetMapHandlerFromStateMachine(__instance);
			if ((Object)(object)mapHandlerFromStateMachine == (Object)null || MapHandlerSegmentsField == null || MapHandlerCurrentSegmentField == null)
			{
				return;
			}
			Array array = MapHandlerSegmentsField.GetValue(mapHandlerFromStateMachine) as Array;
			int num = (int)MapHandlerCurrentSegmentField.GetValue(mapHandlerFromStateMachine);
			if (array != null && num >= 0 && num < array.Length)
			{
				for (int i = 0; i < num; i++)
				{
					ActivateObject(array.GetValue(i), MapSegmentParentField);
					ActivateObject(array.GetValue(i), MapSegmentCampfireField);
				}
				DisableObject(array.GetValue(num), MapSegmentWallPreviousField);
				if (num > 0)
				{
					DisableObject(array.GetValue(num - 1), MapSegmentWallNextField);
				}
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Error in map transition postfix: " + ex));
		}
	}

	private static MapHandler GetMapHandlerFromStateMachine(object stateMachine)
	{
		if (stateMachine == null)
		{
			return null;
		}
		FieldInfo fieldInfo = AccessTools.Field(stateMachine.GetType(), "<>4__this");
		object obj = ((fieldInfo != null) ? fieldInfo.GetValue(stateMachine) : null);
		if (obj == null)
		{
			return null;
		}
		FieldInfo fieldInfo2 = AccessTools.Field(obj.GetType(), "<>4__this");
		return (MapHandler)((fieldInfo2 != null) ? /*isinst with value type is only supported in some contexts*/: null);
	}

	private static void ActivateObject(object mapSegment, FieldInfo field)
	{
		if (mapSegment != null && !(field == null))
		{
			object? value = field.GetValue(mapSegment);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				val.SetActive(true);
			}
		}
	}

	private static void DisableObject(object mapSegment, FieldInfo field)
	{
		if (mapSegment != null && !(field == null))
		{
			object? value = field.GetValue(mapSegment);
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if ((Object)(object)val != (Object)null)
			{
				val.SetActive(false);
			}
		}
	}
}