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().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 Transpiler(IEnumerable instructions) { List list = new List(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); } } } }